Shells¶
Internal shell¶
At any point while debugging, press Ctrl-x
to switch to the built in
interactive shell. From here, you can execute Python commands at the current
point of the debugger. Press Ctrl-x
again to move back to the debugger.
Keyboard shortcuts defined in the internal shell:
Enter |
Execute the current command |
Ctrl-v |
Insert a newline (for multiline commands) |
Ctrl-n/p |
Browse command history |
Up/down arrow |
Select history |
TAB |
Tab completion |
+/- |
grow/shrink the shell (when a history item is selected) |
_/= |
minimize/maximize the shell (when a history item is selected) |
External shells¶
To open the external shell, press the !
key while debugging. Unlike the
internal shell, external shells close the debugger UI while the shell is
active. Press Ctrl-d
at any time to exit the shell and return to the
debugger.
To configure the shell used by PuDB, open the settings (Ctrl-p
) and select
the shell.
PuDB supports the following external shells.
Internal (same as pressing
Ctrl-x
). This is the default.Classic (similar to the default
python
interactive shell)- IPython
The IPython shell can also be used in a server-client fashion, which is enabled by selecting the shell ipython_kernel in the settings. When set, the
!
key will start an IPython kernel and wait for connection from, e.g., qtconsole. Like other shells, ipython_kernel blocks the debugger UI while it is active. Type quit or exit from a client to exit the kernel and return to the debugger.
Custom shells¶
To define a custom external shell, create a file with a function
pudb_shell(_globals, _locals)
at the module level. Then, in
the settings (Ctrl-p
), select “Custom” under the shell settings, and add
the path to the file.
Here is an example custom shell file:
"""
This file shows how you can define a custom shell for PuDB. This is the
shell used when pressing the ! key in the debugger (it does not affect the
Ctrl-x shell that is built into PuDB).
To create a custom shell, create a file like this one with a function called
pudb_shell(_globals, _locals) defined at the module level. Note
that the file will be execfile'd.
Then, go to the PuDB preferences window (type Ctrl-p inside of PuDB) and add
the path to the file in the "Custom" field under the "Shell" heading.
The example in this file
"""
# Define this a function with this name and signature at the module level.
def pudb_shell(_globals, _locals):
"""
This example shell runs a classic Python shell. It is based on
run_classic_shell in pudb.shell.
"""
# Many shells only let you pass in a single locals dictionary, rather than
# separate globals and locals dictionaries. In this case, you can use
# pudb.shell.SetPropagatingDict to automatically merge the two into a
# single dictionary. It does this in such a way that assignments propagate
# to _locals, so that when the debugger is at the module level, variables
# can be reassigned in the shell.
from pudb.shell import SetPropagatingDict
ns = SetPropagatingDict([_locals, _globals], _locals)
try:
import readline
import rlcompleter
have_readline = True
except ImportError:
have_readline = False
if have_readline:
readline.set_completer(
rlcompleter.Completer(ns).complete)
readline.parse_and_bind("tab: complete")
readline.clear_history()
from code import InteractiveConsole
cons = InteractiveConsole(ns)
cons.interact("Press Ctrl-D to return to the debugger")
# When the function returns, control will be returned to the debugger.
Note, many shells do not allow passing in globals and locals dictionaries separately. In this case, you can merge the two with
from pudb.shell import SetPropagatingDict
ns = SetPropagatingDict([_locals, _globals], _locals)
Here is more information on SetPropagatingDict
:
- class pudb.shell.SetPropagatingDict(source_dicts, target_dict)[source]¶
Combine dict into one, with assignments affecting a target dict
The source dicts are combined so that early dicts in the list have higher precedence.
Typical usage is
SetPropagatingDict([locals, globals], locals)
. This is used for functions likerlcompleter.Completer
andcode.InteractiveConsole
, which only take a single dictionary. This way, changes made to it are propagated to locals. Note that assigning to locals only actually works at the module level, whenlocals()
is the same asglobals()
, so propagation doesn’t happen at all if the debugger is inside a function frame.