0
# IPython Integration
1
2
Integration with IPython kernels and GUI toolkits for debugging interactive computing environments. This module supports matplotlib, Qt applications, and other GUI frameworks commonly used in scientific computing, data analysis, and interactive development workflows.
3
4
## Capabilities
5
6
### IPython Kernel Integration
7
8
Core functionality for integrating PyDevD with IPython kernels and Jupyter notebooks.
9
10
```python { .api }
11
# IPython kernel integration utilities
12
13
def setup_ipython_debugging(kernel=None):
14
"""
15
Set up debugging support for IPython kernel.
16
17
Parameters:
18
- kernel: IPython kernel instance (auto-detected if None)
19
20
Returns:
21
None
22
"""
23
24
def enable_ipython_breakpoints():
25
"""
26
Enable breakpoint support in IPython environments.
27
28
Allows using debugger breakpoints within IPython cells and notebooks.
29
30
Returns:
31
None
32
"""
33
34
def get_ipython_frame_context(frame):
35
"""
36
Extract IPython-specific context from debugging frame.
37
38
Parameters:
39
- frame: Python frame object from IPython execution
40
41
Returns:
42
dict: IPython context including cell information, magic commands, and variables
43
"""
44
```
45
46
### GUI Toolkit Event Loop Integration
47
48
Input hook management for various GUI toolkits to ensure proper event loop integration during debugging.
49
50
```python { .api }
51
# GUI toolkit integration from pydev_ipython.inputhook
52
53
def enable_gui(gui=None):
54
"""
55
Enable GUI event loop integration for debugging.
56
57
Parameters:
58
- gui (str, optional): GUI toolkit ('qt', 'qt4', 'qt5', 'tk', 'gtk', 'wx', 'osx')
59
60
Returns:
61
None
62
"""
63
64
def disable_gui():
65
"""
66
Disable GUI event loop integration.
67
68
Returns:
69
None
70
"""
71
72
def set_inputhook(callback):
73
"""
74
Set custom input hook for GUI integration.
75
76
Parameters:
77
- callback: Function to call during input waiting
78
79
Returns:
80
None
81
"""
82
83
def clear_inputhook():
84
"""
85
Clear the current input hook.
86
87
Returns:
88
None
89
"""
90
```
91
92
### Qt Integration
93
94
Specialized support for Qt applications (PyQt4, PyQt5, PySide, PySide2) in debugging environments.
95
96
```python { .api }
97
# Qt integration from pydev_ipython.qt and pydev_ipython.qt_for_kernel
98
99
def create_qapp_for_debugging():
100
"""
101
Create QApplication instance suitable for debugging.
102
103
Returns:
104
QApplication: Qt application instance configured for debugging
105
"""
106
107
def setup_qt_debugging(app=None):
108
"""
109
Set up Qt application for debugging integration.
110
111
Parameters:
112
- app: QApplication instance (created if None)
113
114
Returns:
115
None
116
"""
117
118
def enable_qt_inputhook():
119
"""
120
Enable Qt input hook for event loop integration.
121
122
Returns:
123
None
124
"""
125
126
def process_qt_events():
127
"""
128
Process pending Qt events during debugging.
129
130
Returns:
131
None
132
"""
133
```
134
135
### Matplotlib Integration
136
137
Tools for debugging matplotlib-based plotting and visualization code.
138
139
```python { .api }
140
# Matplotlib integration from pydev_ipython.matplotlibtools
141
142
def configure_matplotlib_backend(backend='Qt5Agg'):
143
"""
144
Configure matplotlib backend for debugging compatibility.
145
146
Parameters:
147
- backend (str): Matplotlib backend name
148
149
Returns:
150
None
151
"""
152
153
def enable_matplotlib_debugging():
154
"""
155
Enable debugging support for matplotlib plotting.
156
157
Ensures plots remain interactive during debugging sessions.
158
159
Returns:
160
None
161
"""
162
163
def show_plot_in_debugger(figure=None):
164
"""
165
Display matplotlib plot in debugging-compatible mode.
166
167
Parameters:
168
- figure: Matplotlib figure instance (current figure if None)
169
170
Returns:
171
None
172
"""
173
174
def get_matplotlib_figures():
175
"""
176
Get all active matplotlib figures for debugging inspection.
177
178
Returns:
179
list: List of active matplotlib figure objects
180
"""
181
```
182
183
### Toolkit-Specific Input Hooks
184
185
Individual input hook implementations for different GUI toolkits.
186
187
```python { .api }
188
# Toolkit-specific hooks from pydev_ipython.inputhook*
189
190
def inputhook_qt4():
191
"""Qt4/PyQt4 input hook implementation."""
192
193
def inputhook_qt5():
194
"""Qt5/PyQt5 input hook implementation."""
195
196
def inputhook_tk():
197
"""Tkinter input hook implementation."""
198
199
def inputhook_gtk():
200
"""GTK input hook implementation."""
201
202
def inputhook_wx():
203
"""wxPython input hook implementation."""
204
205
def inputhook_osx():
206
"""macOS Cocoa input hook implementation."""
207
```
208
209
## Usage Examples
210
211
### Basic IPython Debugging Setup
212
213
```python
214
import pydevd
215
from pydev_ipython import setup_ipython_debugging, enable_ipython_breakpoints
216
217
# Set up PyDevD for IPython
218
pydevd.settrace('localhost', port=5678, suspend=False)
219
220
# Enable IPython-specific debugging features
221
setup_ipython_debugging()
222
enable_ipython_breakpoints()
223
224
# Now you can use breakpoints in IPython cells
225
def analyze_data(data):
226
import pandas as pd
227
df = pd.DataFrame(data)
228
229
# This breakpoint will work in Jupyter notebook
230
breakpoint() # or pydevd.set_trace()
231
232
result = df.describe()
233
return result
234
235
# Example usage in notebook cell
236
data = {'x': [1, 2, 3, 4, 5], 'y': [2, 4, 6, 8, 10]}
237
analysis = analyze_data(data)
238
```
239
240
### Qt Application Debugging
241
242
```python
243
import sys
244
import pydevd
245
from PyQt5.QtWidgets import QApplication, QMainWindow, QVBoxLayout, QWidget, QPushButton
246
from pydev_ipython.qt import setup_qt_debugging, enable_qt_inputhook
247
248
# Set up debugging first
249
pydevd.settrace('localhost', port=5678, suspend=False)
250
251
class DebugMainWindow(QMainWindow):
252
def __init__(self):
253
super().__init__()
254
self.init_ui()
255
256
def init_ui(self):
257
self.setWindowTitle('Qt Debugging Example')
258
self.setGeometry(300, 300, 300, 200)
259
260
central_widget = QWidget()
261
self.setCentralWidget(central_widget)
262
263
layout = QVBoxLayout()
264
central_widget.setLayout(layout)
265
266
button = QPushButton('Click me for debugging')
267
button.clicked.connect(self.on_button_click)
268
layout.addWidget(button)
269
270
def on_button_click(self):
271
# This breakpoint will work with Qt event loop
272
print("Button clicked - setting breakpoint")
273
import pydevd; pydevd.set_trace()
274
275
# Debug Qt application state
276
print(f"Window title: {self.windowTitle()}")
277
print(f"Window size: {self.size()}")
278
279
# Create Qt application
280
app = QApplication(sys.argv)
281
282
# Set up Qt debugging integration
283
setup_qt_debugging(app)
284
enable_qt_inputhook()
285
286
# Create and show main window
287
window = DebugMainWindow()
288
window.show()
289
290
# Start event loop (debugging will work properly)
291
app.exec_()
292
```
293
294
### Matplotlib Debugging
295
296
```python
297
import numpy as np
298
import matplotlib.pyplot as plt
299
import pydevd
300
from pydev_ipython.matplotlibtools import (
301
configure_matplotlib_backend,
302
enable_matplotlib_debugging,
303
show_plot_in_debugger
304
)
305
306
# Set up debugging
307
pydevd.settrace('localhost', port=5678, suspend=False)
308
309
# Configure matplotlib for debugging
310
configure_matplotlib_backend('Qt5Agg')
311
enable_matplotlib_debugging()
312
313
def debug_plot_creation():
314
# Generate sample data
315
x = np.linspace(0, 10, 100)
316
y1 = np.sin(x)
317
y2 = np.cos(x)
318
319
# Set breakpoint before plotting
320
import pydevd; pydevd.set_trace()
321
322
# Create plots (debugger can inspect data here)
323
plt.figure(figsize=(10, 6))
324
plt.subplot(2, 1, 1)
325
plt.plot(x, y1, 'b-', label='sin(x)')
326
plt.legend()
327
plt.grid(True)
328
329
plt.subplot(2, 1, 2)
330
plt.plot(x, y2, 'r-', label='cos(x)')
331
plt.legend()
332
plt.grid(True)
333
334
# Show plot in debugging-compatible mode
335
show_plot_in_debugger()
336
337
return plt.gcf() # Return current figure
338
339
# Create and debug plots
340
figure = debug_plot_creation()
341
```
342
343
### Advanced IPython Integration
344
345
```python
346
import pydevd
347
from pydev_ipython import (
348
setup_ipython_debugging,
349
enable_ipython_breakpoints,
350
get_ipython_frame_context
351
)
352
353
class IPythonDebugManager:
354
def __init__(self, debugger_port=5678):
355
self.debugger_port = debugger_port
356
self.debugging_active = False
357
358
def start_debugging(self):
359
"""Start IPython debugging session."""
360
try:
361
# Set up basic debugging
362
pydevd.settrace(
363
'localhost',
364
port=self.debugger_port,
365
suspend=False,
366
trace_only_current_thread=False
367
)
368
369
# Enable IPython-specific features
370
setup_ipython_debugging()
371
enable_ipython_breakpoints()
372
373
self.debugging_active = True
374
print(f"✓ IPython debugging started on port {self.debugger_port}")
375
376
except Exception as e:
377
print(f"Failed to start IPython debugging: {e}")
378
379
def debug_cell_execution(self, cell_code):
380
"""Debug IPython cell execution with context inspection."""
381
if not self.debugging_active:
382
print("Debugging not active. Call start_debugging() first.")
383
return
384
385
print(f"Executing cell with debugging:\n{cell_code}")
386
387
# Add debugging context
388
debug_wrapper = f"""
389
import pydevd
390
import sys
391
from pydev_ipython import get_ipython_frame_context
392
393
def debug_cell():
394
frame = sys._getframe()
395
context = get_ipython_frame_context(frame)
396
print(f"IPython context: {{context}}")
397
398
# Set breakpoint before user code
399
pydevd.set_trace()
400
401
# User cell code
402
{cell_code}
403
404
debug_cell()
405
"""
406
407
# Execute wrapped code
408
try:
409
exec(debug_wrapper, globals())
410
except Exception as e:
411
print(f"Cell execution error: {e}")
412
413
def stop_debugging(self):
414
"""Stop debugging session."""
415
if self.debugging_active:
416
pydevd.stoptrace()
417
self.debugging_active = False
418
print("Debugging stopped")
419
420
# Usage example
421
debug_manager = IPythonDebugManager(debugger_port=5678)
422
debug_manager.start_debugging()
423
424
# Example cell to debug
425
sample_cell = """
426
import pandas as pd
427
import numpy as np
428
429
# Create sample data
430
data = {
431
'name': ['Alice', 'Bob', 'Charlie'],
432
'age': [25, 30, 35],
433
'score': [95, 87, 92]
434
}
435
436
df = pd.DataFrame(data)
437
print("DataFrame created:")
438
print(df)
439
440
# Perform analysis
441
mean_age = df['age'].mean()
442
max_score = df['score'].max()
443
444
print(f"Mean age: {mean_age}")
445
print(f"Max score: {max_score}")
446
"""
447
448
# Debug the cell
449
debug_manager.debug_cell_execution(sample_cell)
450
```
451
452
### Multi-GUI Toolkit Support
453
454
```python
455
import pydevd
456
from pydev_ipython.inputhook import enable_gui, disable_gui
457
458
def setup_multi_gui_debugging():
459
"""Set up debugging for multiple GUI toolkits."""
460
461
# Start debugging
462
pydevd.settrace('localhost', port=5678, suspend=False)
463
464
# Detect and configure available GUI toolkits
465
available_guis = []
466
467
try:
468
import PyQt5
469
available_guis.append('qt5')
470
except ImportError:
471
pass
472
473
try:
474
import tkinter
475
available_guis.append('tk')
476
except ImportError:
477
pass
478
479
try:
480
import matplotlib
481
available_guis.append('matplotlib')
482
except ImportError:
483
pass
484
485
print(f"Available GUI toolkits: {available_guis}")
486
487
# Enable primary GUI (Qt5 preferred)
488
if 'qt5' in available_guis:
489
enable_gui('qt5')
490
print("Qt5 GUI integration enabled")
491
elif 'tk' in available_guis:
492
enable_gui('tk')
493
print("Tkinter GUI integration enabled")
494
495
return available_guis
496
497
def switch_gui_backend(gui_name):
498
"""Switch to different GUI backend during debugging."""
499
try:
500
disable_gui()
501
enable_gui(gui_name)
502
print(f"Switched to {gui_name} GUI backend")
503
except Exception as e:
504
print(f"Failed to switch to {gui_name}: {e}")
505
506
# Set up multi-GUI debugging
507
available = setup_multi_gui_debugging()
508
509
# Example: Switch between GUI backends
510
if 'qt5' in available and 'tk' in available:
511
# Start with Qt5
512
print("Starting with Qt5...")
513
514
# Switch to Tkinter
515
switch_gui_backend('tk')
516
517
# Switch back to Qt5
518
switch_gui_backend('qt5')
519
```
520
521
### Jupyter Notebook Debugging
522
523
```python
524
# Cell 1: Setup debugging
525
import pydevd
526
from pydev_ipython import setup_ipython_debugging, enable_ipython_breakpoints
527
528
pydevd.settrace('localhost', port=5678, suspend=False)
529
setup_ipython_debugging()
530
enable_ipython_breakpoints()
531
532
print("Debugging enabled for Jupyter notebook")
533
534
# Cell 2: Debug data processing
535
def process_notebook_data():
536
import pandas as pd
537
import numpy as np
538
539
# Create sample dataset
540
np.random.seed(42)
541
data = {
542
'feature1': np.random.normal(0, 1, 1000),
543
'feature2': np.random.normal(0, 1, 1000),
544
'target': np.random.choice([0, 1], 1000)
545
}
546
547
df = pd.DataFrame(data)
548
549
# Set breakpoint for data inspection
550
import pydevd; pydevd.set_trace()
551
552
# Data analysis (debugger can inspect here)
553
correlation = df.corr()
554
summary_stats = df.describe()
555
556
return df, correlation, summary_stats
557
558
# Execute with debugging
559
df, corr, stats = process_notebook_data()
560
561
# Cell 3: Debug visualization
562
import matplotlib.pyplot as plt
563
from pydev_ipython.matplotlibtools import enable_matplotlib_debugging
564
565
enable_matplotlib_debugging()
566
567
def create_debug_plots(dataframe):
568
# Set breakpoint before plotting
569
import pydevd; pydevd.set_trace()
570
571
fig, ((ax1, ax2), (ax3, ax4)) = plt.subplots(2, 2, figsize=(12, 10))
572
573
# Plot 1: Feature distribution
574
ax1.hist(dataframe['feature1'], bins=30, alpha=0.7)
575
ax1.set_title('Feature 1 Distribution')
576
577
# Plot 2: Feature correlation
578
ax2.scatter(dataframe['feature1'], dataframe['feature2'], alpha=0.5)
579
ax2.set_title('Feature Correlation')
580
581
# Plot 3: Target distribution
582
target_counts = dataframe['target'].value_counts()
583
ax3.bar(target_counts.index, target_counts.values)
584
ax3.set_title('Target Distribution')
585
586
# Plot 4: Box plot
587
ax4.boxplot([dataframe['feature1'], dataframe['feature2']],
588
labels=['Feature 1', 'Feature 2'])
589
ax4.set_title('Feature Box Plots')
590
591
plt.tight_layout()
592
plt.show()
593
594
return fig
595
596
# Create plots with debugging
597
figure = create_debug_plots(df)
598
```
599
600
## Configuration Options
601
602
### GUI Backend Configuration
603
604
```python
605
# Available GUI backends
606
GUI_BACKENDS = {
607
'qt4': 'PyQt4/PySide',
608
'qt5': 'PyQt5/PySide2',
609
'tk': 'Tkinter',
610
'gtk': 'GTK+',
611
'wx': 'wxPython',
612
'osx': 'macOS Cocoa'
613
}
614
615
# Matplotlib backend mapping
616
MATPLOTLIB_BACKENDS = {
617
'qt4': 'Qt4Agg',
618
'qt5': 'Qt5Agg',
619
'tk': 'TkAgg',
620
'gtk': 'GTK3Agg',
621
'wx': 'WXAgg',
622
'osx': 'MacOSX'
623
}
624
```
625
626
### Performance Considerations
627
628
- **Event Loop Integration**: Minimal overhead added to GUI event loops
629
- **Input Hook Efficiency**: Optimized input hooks for different toolkits
630
- **Matplotlib Backend**: Some backends perform better than others for debugging
631
- **Memory Usage**: IPython integration may increase memory usage during debugging
632
- **Threading**: Proper thread safety for multi-threaded GUI applications