Full-screen console debugger for Python

Overview

PuDB: a console-based visual debugger for Python

Gitlab Build Status Github Build Status Python Package Index Release Page

Its goal is to provide all the niceties of modern GUI-based debuggers in a more lightweight and keyboard-friendly package. PuDB allows you to debug code right where you write and test it--in a terminal. If you've worked with the excellent (but nowadays ancient) DOS-based Turbo Pascal or C tools, PuDB's UI might look familiar.

Here's a screenshot:

https://tiker.net/pub/pudb-screenshot.png

You may watch a screencast, too.

Features

  • Syntax-highlighted source, the stack, breakpoints and variables are all visible at once and continuously updated. This helps you be more aware of what's going on in your program. Variable displays can be expanded, collapsed and have various customization options.
  • Simple, keyboard-based navigation using single keystrokes makes debugging quick and easy. PuDB understands cursor-keys and Vi shortcuts for navigation. Other keys are inspired by the corresponding pdb commands.
  • Use search to find relevant source code, or use "m" to invoke the module browser that shows loaded modules, lets you load new ones and reload existing ones.
  • Breakpoints can be set just by pointing at a source line and hitting "b" and then edited visually in the breakpoints window. Or hit "t" to run to the line under the cursor.
  • Drop to a Python shell in the current environment by pressing "!". Or open a command prompt alongside the source-code via "Ctrl-X".
  • PuDB places special emphasis on exception handling. A post-mortem mode makes it easy to retrace a crashing program's last steps.
  • Ability to control the debugger from a separate terminal.
  • IPython integration (see wiki)
  • Should work with Python 3.6 and newer. (Versions 2019.2 and older continue to support Python 2.7.)

Links

PuDB documentation

PuDB also has a mailing list that you may use to submit patches and requests for help. You can also send a pull request to the GitHub repository

Development Version

You may obtain the development version using the Git version control tool.:

git clone https://github.com/inducer/pudb.git

You may also browse the code online.

Issues
  • Ctrl-x not function to leave console

    Ctrl-x not function to leave console

    When attempting to make local calls in the console, pressing ctrl-x merely prints ^x rather than leaving the console. At this point, the only way out is to kill pudb. An interesting behavior is that this only happens after issuing a command in the console; ctrl-x works fine until then.

    Details: pudb version: 2015.4.1 installed with pip running in osx 10.11.2 in iTerm2, Terminal, and Neovim's terminal mode

    opened by ghost 58
  • A way to un-breakpoint a set_trace() line

    A way to un-breakpoint a set_trace() line

    This sounds kind of odd, let me explain. I usually enter the debugger with an explicit call to set_trace(). Often, once I've hit that line a few times, I no longer need to stop there, but I don't want to restart the process.

    Just as I can manually turn a regular line into a breakpoint with the 'b' command, I would love a way to turn a set_trace() line back into a regular, non-breaking line. The set_trace function would still be called of course, but could examine the calling line to see if it had been marked as non-breaking, and continue.

    enhancement 
    opened by nedbat 33
  • Add set_continue() function to __init__.py

    Add set_continue() function to __init__.py

    This lets you start the debugger and immediately continue, i.e., it only stops on a previously defined breakpoint.

    Fixes #234.

    Let me know if you would prefer a better name, or just a flag to set_trace().

    opened by asmeurer 22
  • Two New Features

    Two New Features

    Hey there. Here are two features I've wanted for a little while (sorry, probably should have put them in separate branches but they're small and you should be able to cherry pick if you don't want both).

    One of them adds support for bpython-urwid (I think maybe I'll experiment later with getting this to run inside pudb's mainloop, since that can open up some possibilities).

    The other adds support for specifying an arbitrary expression to use as the stringifier for each variable.

    opened by Julian 22
  • Problems when setting breakpoints

    Problems when setting breakpoints

    When I try to set a breakpoin, I get the errormessage: The breakpoint you just set may be invalid, for the following reason: File failed to compile.

    I can set breakpoint with Set Anyway. After some debugging, the breakpoint(s) disappear.

    Version of pudb is 2017.1, python 2.7.12+ and Ubuntu 16.10.

    Eivind

    opened by enmy211 21
  • running set_trace() multiple times displays stdlib bdb.py

    running set_trace() multiple times displays stdlib bdb.py

    Reproduction steps:

    1. Save below script as foobar.py
    2. python foobar.py foo bar
    3. You'll break at function foo
    4. Defined a breakpoint at foobar.py:11 (the first line of main(): for arg in argv:)
    5. c
    6. You'll be brought to line 11
    7. c
    8. You'll be brought to /usr/lib/python2.6/bdb.py at _ste_stopinfo(), and also see that you now have two breakpoints at foobar.py:11
    9. Pressing s fourteen times eventually brings you to the correct breakpoint in bar()

    The expected behavior is to not display bdb.py, and not create duplicate breakpoints.

    Obviously there are other ways to accomplish the desired debugging session, but in a large, complex code base, it is sometimes extremely convenient to have multiple set_trace lines, which may or may not cause set_trace to be called twice.

    If you can tell me how to induce this error automatically, I can write a unit test for it, at minimum, and likely produce a patch for the bug as well.

    # Script: foobar.py
    def foo():
        import pudb; pudb.set_trace()
        print 'foo'
    
    def bar():
        import pudb; pudb.set_trace()
        print 'bar'
    
    def main(argv):
        for arg in argv:
            if arg == 'foo':
                foo()
            elif arg == 'bar':
                bar()
    
    import sys
    main(sys.argv)
    
    Bug 
    opened by bukzor 20
  • don't provoke undefined signal handling

    don't provoke undefined signal handling

    mod_wsgi installs a non-default signal handler for SIGINT.

    The current behavior of pudb utterly clobbers this signal handler and causes undefined behavior (in practice, the process becomes impossible to kill with SIGINT).

    Until pudb has better support for non-default signal handlers in the process-under-test, I've added this small amount of code to detect the situation, throw a warning, and continue without interrupt support.

    The new warning looks like this under apache.

    [Mon Jun 10 18:44:30 2013] [error] /home/buck/trees/theirs/pudb/pudb/__init__.py:166: UserWarning: A non-default handler for signal 2 is already installed (not installed from python). Skipping pudb interrupt support.
    [Mon Jun 10 18:44:30 2013] [error]   % (interrupt_signal, old_handler))
    

    Then the process continues to work as well as previous versions of pudb.

    In terms of priority, this is driving everyone that has upgraded pudb completely nuts, and the only recourse is to downgrade.

    opened by bukzor 18
  • Add mouse support and a few changes/fix

    Add mouse support and a few changes/fix

    I know I should have asked when I started adding mouse support. So, I will highlight the changes I have made:

    mouse support

    • add
      • class double_press_input_filter for double click,
      • def listen_mouse_event like def listen, and
      • def mouse_event like def keypress for mouse support.
    • change some event handlers because the argument difference of key event and mouse event, e.g. def move_down(w, size, key) to move_down(w, size, *args). Almost all of those handlers I changed don't use key at all.
    • add some mouse event handler, which are not documented in HELP yet.

    changes

    • change change_rhs_box sizing method, which cause both above and below the selected sidebox resize, which is strange to me. I changed it so it would only affect the box below.
    • add non_post_mortem_only decorator, just try to reduce few lines.

    fix

    • exception when key press on empty variables list.

    It's fine if no one else wants the mouse support; however if it's accepted, but some naming or style/method don't fit into pudb, please let me know I will add additional changes to meet the need.

    The two changes I made, especially first one, might need more input because not everyone likes the sizing method I like as I don't like the current.

    enhancement 
    opened by livibetter 16
  • Latest PuDB (2017.1.3) dies with ListBoxError in some cases

    Latest PuDB (2017.1.3) dies with ListBoxError in some cases

    Stacktrace (edited slightly for anonymity):

      File "/usr/lib/python2.7/bdb.py", line 49, in trace_dispatch
        return self.dispatch_line(frame)
      File ".../site-packages/pudb/debugger.py", line 160, in dispatch_line
        self.user_line(frame)
      File ".../site-packages/pudb/debugger.py", line 381, in user_line
        self.interaction(frame)
      File ".../site-packages/pudb/debugger.py", line 349, in interaction
        show_exc_dialog=show_exc_dialog)
      File ".../site-packages/pudb/debugger.py", line 2084, in call_with_ui
        return f(*args, **kwargs)
      File ".../site-packages/pudb/debugger.py", line 2322, in interaction
        self.event_loop()
      File ".../site-packages/pudb/debugger.py", line 2280, in event_loop
        canvas = toplevel.render(self.size, focus=True)
      File ".../site-packages/urwid/widget.py", line 141, in cached_render
        canv = fn(self, size, focus=focus)
      File ".../site-packages/urwid/widget.py", line 1751, in render
        canv = get_delegate(self).render(size, focus=focus)
      File ".../site-packages/urwid/widget.py", line 141, in cached_render
        canv = fn(self, size, focus=focus)
      File ".../site-packages/urwid/container.py", line 1083, in render
        focus and self.focus_part == 'body')
      File ".../site-packages/urwid/widget.py", line 141, in cached_render
        canv = fn(self, size, focus=focus)
      File ".../site-packages/urwid/decoration.py", line 225, in render
        canv = self._original_widget.render(size, focus=focus)
      File ".../site-packages/urwid/widget.py", line 141, in cached_render
        canv = fn(self, size, focus=focus)
      File ".../site-packages/urwid/container.py", line 2085, in render
        focus = focus and self.focus_position == i)
      File ".../site-packages/urwid/widget.py", line 141, in cached_render
        canv = fn(self, size, focus=focus)
      File ".../site-packages/urwid/widget.py", line 1751, in render
        canv = get_delegate(self).render(size, focus=focus)
      File ".../site-packages/urwid/widget.py", line 141, in cached_render
        canv = fn(self, size, focus=focus)
      File ".../site-packages/urwid/container.py", line 1526, in render
        canv = w.render((maxcol, rows), focus=focus and item_focus)
      File ".../site-packages/urwid/widget.py", line 141, in cached_render
        canv = fn(self, size, focus=focus)
      File ".../site-packages/urwid/decoration.py", line 225, in render
        canv = self._original_widget.render(size, focus=focus)
      File ".../site-packages/urwid/widget.py", line 141, in cached_render
        canv = fn(self, size, focus=focus)
      File ".../site-packages/urwid/container.py", line 1526, in render
        canv = w.render((maxcol, rows), focus=focus and item_focus)
      File ".../site-packages/urwid/widget.py", line 141, in cached_render
        canv = fn(self, size, focus=focus)
      File ".../site-packages/urwid/decoration.py", line 225, in render
        canv = self._original_widget.render(size, focus=focus)
      File ".../site-packages/urwid/widget.py", line 141, in cached_render
        canv = fn(self, size, focus=focus)
      File ".../site-packages/urwid/widget.py", line 1751, in render
        canv = get_delegate(self).render(size, focus=focus)
      File ".../site-packages/urwid/widget.py", line 141, in cached_render
        canv = fn(self, size, focus=focus)
      File ".../site-packages/urwid/listbox.py", line 489, in render
        raise ListBoxError, "Widget %r at position %r within listbox calculated %d rows but rendered %d!"% (widget,w_pos,w_rows, canvas.rows())
    ListBoxError: Widget <VariableWidget selectable flow widget> at position 3 within listbox calculated 1 rows but rendered 0!
    

    This happens under Ubuntu 17.04 using Gnome Terminal (pudb is being run inside of a docker container also running Ubuntu 17.04 if it matters). The error goes away when using PuDB 2017.1.2. It also seems to be dependent on the terminal size. For example it happens both with my "maximized" terminal size (158x46) as well as at 132x43, but it does not happen when the terminal is resized to 80x24. My pudb.cfg:

    [pudb]
    breakpoints_weight = 1
    current_stack_frame = top
    custom_shell = 
    custom_stringifier = 
    custom_theme = 
    display = auto
    line_numbers = True
    prompt_on_quit = True
    seen_welcome = e032
    shell = internal
    sidebar_width = 0.5
    stack_weight = 1
    stringifier = type
    theme = classic
    variables_weight = 1
    wrap_variables = True
    

    This is also potentially related to #269

    opened by cdman 14
  • Fix make_canvas for lines with multiple attrs

    Fix make_canvas for lines with multiple attrs

    As I was saying in #174, I was seeing some dangling characters issue. The issue was more severe than that, because I was always using line[i:count] instead of line[i:i+count]. To ensure this two chars fix works I added unit tests. They can be run by using 'py.test' from the root pudb directory.

    opened by pquentin 14
  • crash on long unicode line

    crash on long unicode line

    The system is getting confused about the difference between number-of-characters and number-of-bytes here. It's unclear to me whether this is the fault of pudb or urwid.

      File "/nail/home/buck/venv/testify/lib/python2.6/site-packages/urwid/canvas.py", line 356, in __init__
        raise CanvasError("Canvas text is wider than the maxcol specified \n%r\n%r\n%r"%(maxcol,widths,text))
    CanvasError: Canvas text is wider than the maxcol specified 
    87
    [91]
    ["          alternate_names = {'en': [{'name': u'F\xc3\xa4milyM\xc3\xa4rt'}], 'ja': [{'name': u'\xe3\x83\x95\xe3\x82\xa1\xe3\x83\x9f\xe3\x83\x9e'},"]
    
    opened by bukzor 14
  • [feature] Add shell completion

    [feature] Add shell completion

    opened by Freed-Wu 0
  • Add --config to use customize configuration file

    Add --config to use customize configuration file

    Is your feature request related to a problem? Please describe. No

    Describe the solution you'd like

    $ pudb3 --help
    usage: pudb3 [options] [-m] SCRIPT-OR-MODULE-TO-RUN [SCRIPT_ARGS]
    
    positional arguments:
      script_args           Arguments to pass to script or module
    
    optional arguments:
      -h, --help            show this help message and exit
      -s, --steal-output
      -m, --module          Debug as module or package instead of as a script
      -le FILE, --log-errors FILE
                            Log internal errors to the given file
      --pre-run COMMAND     Run command before each program run
      --config CONFIG       Use config file [Default: ~/.config/pudb/pudb.cfg]
      --version             show program's version number and exit
    
    pudb:pudb3 v2022.1.2
    
    enhancement 
    opened by Freed-Wu 2
  • Drop support for Python 3.6-

    Drop support for Python 3.6-

    Hi,

    This came up when I was checking out TUI libraries to replace urwid, and encountered textual.

    It is from the authors of rich, and so runs on Linux/Mac/Windows.

    It supports Python 3.7+ - https://github.com/Textualize/textual/blob/main/pyproject.toml

    If I were to start looking into swapping urwid, then new versions of PuDB would lose support for deprecated Python versions (Python 3.6 is no longer maintained - https://endoflife.date/python), so I was wondering if that would be agreeable.

    Thanks, Eli

    enhancement 
    opened by h5rdly 1
  • Add global and

    Add global and "by reference" watches

    Addresses #511

    Allows modifying watch expressions in two ways:

    1. Whether to show the watch expression in all frames as opposed to only the current frame
    2. Whether to continually re-evaluate the watch expression or evaluate it when it is created, cache the result, and watch changes to this value over time. If the value appears in the current local or global namespaces, it's current name is shown in parentheses.
    opened by mvanderkamp 3
  • Monkeypatch `dataclasses` so that its generated code becomes debuggable

    Monkeypatch `dataclasses` so that its generated code becomes debuggable

    The difficulty here is going to be to do this reasonably robustly, perhaps by explicitly listing Python versions for which it is OK. All that's necessary is to patch this function:

    https://github.com/python/cpython/blob/d71f5adc41569c2d626552269797e0545fc9122c/Lib/dataclasses.py#L413-L436=

    enhancement 
    opened by inducer 0
Releases(v2022.1.2)
Dahua Console, access internal debug console and/or other researched functions in Dahua devices.

Dahua Console, access internal debug console and/or other researched functions in Dahua devices.

bashis 125 Jul 28, 2022
pdb++, a drop-in replacement for pdb (the Python debugger)

pdb++, a drop-in replacement for pdb What is it? This module is an extension of the pdb module of the standard library. It is meant to be fully compat

null 951 Aug 5, 2022
Debugger capable of attaching to and injecting code into python processes.

DISCLAIMER: This is not an official google project, this is just something I wrote while at Google. Pyringe What this is Pyringe is a python debugger

Google 1.6k Aug 1, 2022
pdb++, a drop-in replacement for pdb (the Python debugger)

pdb++, a drop-in replacement for pdb What is it? This module is an extension of the pdb module of the standard library. It is meant to be fully compat

null 951 Aug 5, 2022
Graphical Python debugger which lets you easily view the values of all evaluated expressions

birdseye birdseye is a Python debugger which records the values of expressions in a function call and lets you easily view them after the function exi

Alex Hall 1.5k Aug 9, 2022
Voltron is an extensible debugger UI toolkit written in Python.

Voltron is an extensible debugger UI toolkit written in Python. It aims to improve the user experience of various debuggers (LLDB, GDB, VDB an

snare 5.8k Aug 12, 2022
NoPdb: Non-interactive Python Debugger

NoPdb: Non-interactive Python Debugger Installation: pip install nopdb Docs: https://nopdb.readthedocs.io/ NoPdb is a programmatic (non-interactive) d

Ondřej Cífka 62 Jul 15, 2022
Tracing instruction in lldb debugger.Just a python-script for lldb.

lldb-trace Tracing instruction in lldb debugger. just a python-script for lldb. How to use it? Break at an address where you want to begin tracing. Im

null 146 Aug 5, 2022
Visual Interaction with Code - A portable visual debugger for python

VIC Visual Interaction with Code A simple tool for debugging and interacting with running python code. This tool is designed to make it easy to inspec

Nathan Blank 1 Nov 16, 2021
An improbable web debugger through WebSockets

wdb - Web Debugger Description wdb is a full featured web debugger based on a client-server architecture. The wdb server which is responsible of manag

Kozea 1.5k Jul 30, 2022
PINCE is a front-end/reverse engineering tool for the GNU Project Debugger (GDB), focused on games.

PINCE is a front-end/reverse engineering tool for the GNU Project Debugger (GDB), focused on games. However, it can be used for any reverse-engi

Korcan Karaokçu 1.3k Aug 8, 2022
Little helper to run Steam apps under Proton with a GDB debugger

protongdb A small little helper for running games with Proton and debugging with GDB Requirements At least Python 3.5 protontricks pip package and its

Joshie 19 Jul 10, 2022
Arghonaut is an interactive interpreter, visualizer, and debugger for Argh! and Aargh!

Arghonaut Arghonaut is an interactive interpreter, visualizer, and debugger for Argh! and Aargh!, which are Befunge-like esoteric programming language

Aaron Friesen 2 Dec 10, 2021
A simple rubber duck debugger

Rubber Duck Debugger I found myself many times asking a question on StackOverflow or to one of my colleagues just for finding the solution simply by d

null 1 Nov 10, 2021
Hdbg - Historical Debugger

hdbg - Historical Debugger This is in no way a finished product. Do not use this

Fivreld 2 Jan 2, 2022
Trashdbg - TrashDBG the world's worse debugger

The world's worse debugger Over the course of multiple OALABS Twitch streams we

OALabs 21 Jun 17, 2022
The official code of LM-Debugger, an interactive tool for inspection and intervention in transformer-based language models.

LM-Debugger is an open-source interactive tool for inspection and intervention in transformer-based language models. This repository includes the code

Mor Geva 91 Aug 10, 2022
Middleware that Prints the number of DB queries to the runserver console.

Django Querycount Inspired by this post by David Szotten, this project gives you a middleware that prints DB query counts in Django's runserver consol

Brad Montgomery 320 Aug 9, 2022
Trace any Python program, anywhere!

lptrace lptrace is strace for Python programs. It lets you see in real-time what functions a Python program is running. It's particularly useful to de

Karim Hamidou 684 Aug 1, 2022