6

Is there a way to tell Python to halt execution at a certain point in a script and wait for a debugger to attach to the process?

Is there something similar to dot-Net's Debugger.Break() in Python?

Chris Hunt
  • 3,840
  • 3
  • 30
  • 46
Nitzan
  • 1,669
  • 3
  • 19
  • 33

5 Answers5

7

Different IDEs can use different methods for attaching to the process, however PyCharm, Eclipse, Visual Studio, and VS Code all use pydevd (VS/VSC via their Python plugin via ptvsd) to provide their in-process debugger implementation. As a result, we can target those with one piece of code.

The idea is to wait until pydevd is imported and then stop at a breakpoint.

import sys
import threading

from importlib.abc import MetaPathFinder


class NotificationFinder(MetaPathFinder):
    def find_spec(self, fullname, _path, _target=None):
        if 'pydevd' in fullname:
            with t:
                t.notify()

t = threading.Condition()
sys.meta_path.insert(0, NotificationFinder())

with t:
    t.wait()

breakpoint()

Since pydevd creates __builtins__.breakpoint, this should work regardless of the Python version. I tested in PyCharm (Community Edition 2019.1.3). I started the script, attached with the "Attach to process" option in my IDE, and was able to attach successfully. The script then stopped at breakpoint() as expected.

Chris Hunt
  • 3,840
  • 3
  • 30
  • 46
1

Install ipython and ipdb. Afterwards you can just use

import ipdb
ipdb.set_trace()

And debug straight from the console. You can also use pdb which comes straight out of the box:

import pdb
pdb.set_trace()
GLaDOS
  • 620
  • 6
  • 17
  • ipdb is great, but pdb comes built-in with Python. – Daniel Roseman Mar 02 '16 at 15:08
  • Still, I'm very interested in debugging from tools like PyCharm, and from my understanding pdb is limited to the console. Is there a way I could break and attach using a tool like PyCharm? – Nitzan Mar 02 '16 at 15:16
  • Well that would work differently. You can look up tutorials for it like this one: https://www.jetbrains.com/pycharm/help/remote-debugging.html – GLaDOS Mar 02 '16 at 15:22
1

Here is another way you can wait for pydevd:

while not (pydevd.connected and get_global_debugger().ready_to_run):
    sleep(0.3)
breakpoint()

In my setup MetaPathFinder was firing only the first time I would connect with pydevd. With a while loop you should be able to reconnect because you are not relying on pydevd import side effect.

Timofey Solonin
  • 1,393
  • 13
  • 20
0

Improving on Timofey Solonin's answer https://stackoverflow.com/a/66841531/324204.

# ...

import pydevd
import time
while pydevd.get_global_debugger() is None or not pydevd.get_global_debugger().ready_to_run:
    time.sleep(0.3)
breakpoint() # breaks here

# ...

The improvement is to not use pydevd.connected. It is not defined in pydevd version 2.8.

Note that on Linux you may have a problem with having no permissions to attach to the process. How to solve "ptrace operation not permitted" when trying to attach GDB to a process?

Sogartar
  • 2,035
  • 2
  • 19
  • 35
0

You can use my tool madbg to do exactly that. Put this in your program:

madbg.set_trace()

This line will block until a debugger connects using:

madbg connect

madbg could connect from the same machine or over the network. It could also preemptively stop your process and attach to it.

kmaork
  • 5,722
  • 2
  • 23
  • 40