NoPdb: Non-interactive Python Debugger

Overview

NoPdb: Non-interactive Python Debugger

PyPI Package Documentation Status Lint Status Lint Status

NoPdb is a programmatic (non-interactive) debugger for Python. This means it gives you access to debugger-like superpowers directly from your code. With NoPdb, you can:

  • capture function calls, including arguments, local variables, return values and stack traces
  • set "breakpoints" that trigger user-defined actions when hit, namely:
    • evaluate expressions to retrieve their values later
    • execute arbitrary code, including modifying local variables
    • enter an interactive debugger like pdb

NoPdb is also a convenient tool for inspecting machine learning model internals. For example, this notebook shows how to use it to visualize Transformer attention in PyTorch.

NoPdb should run at least under CPython and PyPy. Most features should work under any implementation as long as it has sys.settrace().

Note: This project is in its early development stage. Contributions and improvement ideas are welcome.

Capturing function calls

The functions capture_call() and capture_calls() allow capturing useful information about calls to a given function. They are typically used as context managers, e.g.:

with nopdb.capture_calls(fn) as calls:
    some_code_that_calls_fn()

    print(calls)  # see details about how fn() was called

The information we can retrieve includes the function's arguments, return value, local variables and stack trace. For example:

>>> with nopdb.capture_call(f) as call:
...     g(1)
>>> call
CallCapture(name='f', args=OrderedDict(x=1, y=1), return_value=4)
>>> call.print_stack()
  File "<stdin>", line 2, in <module>
  File "<stdin>", line 2, in g
  File "<stdin>", line 1, in f
>>> call.args['x']
1
>>> call.return_value
4
>>> call.locals
{'y': 1, 'x': 1, 'z': 2}

Setting breakpoints

Like conventional debuggers, NoPdb can set breakpoints. However, because NoPdb is a non-interactive debugger, its breakpoints do not actually stop the execution of the program. Instead, they allow executing actions scheduled in advance, such as evaluating expressions.

To set a breakpoint, call the breakpoint() function. A breakpoint object is returned, allowing to schedule actions using its methods such as eval() and exec(). For example:

# Break at line 3 of the file or notebook cell where f is defined
with nopdb.breakpoint(function=f, line=3) as bp:
    x = bp.eval("x")             # Schedule an expression
    type_y = bp.eval("type(y)")  # Another one
    bp.exec("print(y)")          # Schedule a print statement

    some_code_that_calls_f()

print(x, type_y)  # Retrieve the captured values

There are other ways to specify the breakpoint location. For example:

# Break at any line with the given source code in the given file
with nopdb.breakpoint(file="pathlib.py", line="return obj") as bp:
    ...

# Break as soon as any function with the given name is called
with nopdb.breakpoint(function="myfunc") as bp:
    ...

Not only can we capture values, we can also modify them!

>>> with nopdb.breakpoint(function=f, line=3) as bp:
...     # Get the value of x, then increment it, then get the new value
...     x_before = bp.eval('x')
...     bp.exec('x += 1')
...     x_after = bp.eval('x')
...
...     some_code_that_calls_f()
>>> x_before
[2]
>>> x_after
[3]

Planned features

Functionalities that do not exist, but could be added in the future:

  • Breakpoint.callback() for calling a given callback function, passing information about the current frame as an argument.
  • Breakpoint.jump() for jumping to a different line in the same function.
  • A way to disable breakpoints.

Limitations

  • Like Pdb, NoPdb only works with pure-Python functions. Calls to built-ins and C extensions cannot be captured. This also applies to ML frameworks that compile models into static graphs; for NoPdb to work, this feature needs to be disabled, e.g. with tf.config.run_functions_eagerly(True) in TensorFlow and with the jax.disable_jit() context manager in JAX.
  • Local variable assignment in Breakpoint.exec() is only supported under CPython and PyPy.
You might also like...
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.

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

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

Full featured multi arch/os debugger built on top of PyQt5 and frida

Full featured multi arch/os debugger built on top of PyQt5 and frida

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

Hdbg - Historical Debugger
Hdbg - Historical Debugger

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

Trashdbg - TrashDBG the world's worse debugger
Trashdbg - TrashDBG the world's worse debugger

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

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

Debugging manhole for python applications.

Overview docs tests package Manhole is in-process service that will accept unix domain socket connections and present the stacktraces for all threads

(OLD REPO) Line-by-line profiling for Python - Current repo -

line_profiler and kernprof line_profiler is a module for doing line-by-line profiling of functions. kernprof is a convenient script for running either

Comments
  • Functionality questions

    Functionality questions

    Thanks for making this project. A non-interactive python debugger is exactly what I'm looking for. I'd like to use your project to support the Python probe for Source++. I've been able to successfully implement some portions of the functionality, but I'm having some trouble understanding some Python debugging relating things. I think some of this trouble might be alleviated with new functionality for nopdb and I'm more than willing to implement that functionality. My background is with JVM languages so I'm just looking for a bit of guidance on how things work the Python way.

    Breakpoint doesn't hit on Flask app

    I don't think this issue is a nopdb issue as I'm unable to hit the breakpoint using import pdb; pdb.set_trace() in the main method either. I believe this issue is because of either compiled code within Flask or pdb is not hitting because of separate threads. Either way, I'm able to set breakpoints via PyCharm so it appears to be possible in some way. Hopefully, it's just a threading thing and breakpoints can be placed for every thread. Do you know how this functionality could be implemented with nopdb?

    Here is some code that shows a breakpoint that's never hit:

    import os
    
    from flask import Flask
    from nopdb import nopdb
    
    app = Flask(__name__)
    
    
    @app.route('/')
    def hello():
        provider = str(os.environ.get('PROVIDER', 'world'))
        return 'Hello ' + provider + '!'
    
    
    if __name__ == '__main__':
        with nopdb.breakpoint(file="FlaskTest.py", line=12) as bp:
            bp.exec("print(\"provider: \" + provider)")
            port = int(os.environ.get('PORT', 5000))
            app.run(host='0.0.0.0', port=port)
    
    

    Ability to add breakpoints without calling code via context manager

    This might be related to the issue above, but how do you add breakpoints to code that you don't want to call via the context manager? As in, code that is already running or that will run by itself sometime in the future? I have a small example here where I want to set a breakpoint before a function is called in the future via a delay. Can nopdb address this type of scenario?

    Code which shows a breakpoint that's never hit:

    import threading
    
    from nopdb import nopdb
    
    
    def fun():
        x = 5
        y = x
    
    
    if __name__ == '__main__':
        start_time = threading.Timer(10, fun)
        start_time.start()
    
       # I'd like to set the breakpoint ahead of time and just output x once it's hit
        with nopdb.breakpoint(file="SeparateThread.py", line=8) as bp:
            bp.exec("print(\"x: \" + str(x))")
    
    

    Does cpdb make sense to extend?

    This might be a bit off-topic, but while looking into Python debuggers I ran across https://pypi.org/project/CPdb/. Does this project make sense to extend for nopdb? The reason I ask is because of the claim cpdb makes about "long-running" applications running better with it. I would like to use nopdb in "long-running" applications so I'm curious if it makes sense to integrate the technologies.

    opened by BFergerson 0
Releases(v0.2.0)
Owner
Ondřej Cífka
PhD candidate @ Télécom Paris. Working on music style transfer
Ondřej Cífka
Sweeter debugging and benchmarking Python programs.

Do you ever use print() or log() to debug your code? If so, ycecream, or y for short, will make printing debug information a lot sweeter. And on top o

42 Dec 12, 2022
A configurable set of panels that display various debug information about the current request/response.

Django Debug Toolbar The Django Debug Toolbar is a configurable set of panels that display various debug information about the current request/respons

Jazzband 7.3k Dec 29, 2022
Visual profiler for Python

vprof vprof is a Python package providing rich and interactive visualizations for various Python program characteristics such as running time and memo

Nick Volynets 3.9k Jan 01, 2023
Inject code into running Python processes

pyrasite Tools for injecting arbitrary code into running Python processes. homepage: http://pyrasite.com documentation: http://pyrasite.rtfd.org downl

Luke Macken 2.7k Jan 08, 2023
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

1 Nov 10, 2021
An x86 old-debug-like program.

An x86 old-debug-like program.

Pablo Niklas 1 Jan 10, 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.5k Jan 01, 2023
Sampling profiler for Python programs

py-spy: Sampling profiler for Python programs py-spy is a sampling profiler for Python programs. It lets you visualize what your Python program is spe

Ben Frederickson 9.5k Jan 08, 2023
A powerful set of Python debugging tools, based on PySnooper

snoop snoop is a powerful set of Python debugging tools. It's primarily meant to be a more featureful and refined version of PySnooper. It also includ

Alex Hall 874 Jan 08, 2023
Never use print for debugging again

PySnooper - Never use print for debugging again PySnooper is a poor man's debugger. If you've used Bash, it's like set -x for Python, except it's fanc

Ram Rachum 15.5k Jan 01, 2023
Pyinstrument - a Python profiler. A profiler is a tool to help you optimize your code - make it faster.

Pyinstrument🚴 Call stack profiler for Python. Shows you why your code is slow!

Joe Rickerby 5k Jan 08, 2023
Python's missing debug print command and other development tools.

python devtools Python's missing debug print command and other development tools. For more information, see documentation. Install Just pip install de

Samuel Colvin 637 Jan 02, 2023
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
Trace all method entries and exits, the exit also prints the return value, if it is of basic type

Trace all method entries and exits, the exit also prints the return value, if it is of basic type. The apk must have set the android:debuggable="true" flag.

Kurt Nistelberger 7 Aug 10, 2022
A toolbar overlay for debugging Flask applications

Flask Debug-toolbar This is a port of the excellent django-debug-toolbar for Flask applications. Installation Installing is simple with pip: $ pip ins

863 Dec 29, 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 67 Oct 15, 2022
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.6k Dec 09, 2022
A drop-in replacement for Django's runserver.

About A drop in replacement for Django's built-in runserver command. Features include: An extendable interface for handling things such as real-time l

David Cramer 1.3k Dec 15, 2022
Parsing ELF and DWARF in Python

pyelftools pyelftools is a pure-Python library for parsing and analyzing ELF files and DWARF debugging information. See the User's guide for more deta

Eli Bendersky 1.6k Jan 04, 2023
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