Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Not working python breakpoints in C thread in pycharm or eclipse+pydev

I have a django application using a C++ library (imported via swig). The C++ library launches own thread which calls callbacks in Python code.

I cannot setup a breakpoint in python code, neither in PyDev nor PyCharm. Tried also 'gevent compatibility' option too with no luck.

I verified the callbacks are properly called as logging.info dumps what expected. Breakpoints set in other threads work fine. So it seems that python debuggers cannot manage breakpoints in python code called by threads created in non-python code.

Does anyone know a workaround? Maybe there is some 'magic' thread initialization sequence I could use?

like image 633
Alek Kowalczyk Avatar asked Dec 15 '15 20:12

Alek Kowalczyk


2 Answers

You have to setup the debugger machinery for it to work on non-python threads (this is done automatically when a Python thread is created, but when you create a thread for which Python doesn't have any creation hook, you have to do it yourself) -- note that for some frameworks -- such as QThread/Gevent -- things are monkey patched so that we know about the initialization and start the debugger, but for other frameworks you have to do it yourself.

To do that, after starting the thread you have to call:

import pydevd
pydevd.settrace(suspend=False, trace_only_current_thread=True)

Note that if you had put suspend=True, it'd simulate a manual breakpoint and would stop at that point of the code.

like image 151
Fabio Zadrozny Avatar answered Nov 03 '22 00:11

Fabio Zadrozny


This is a follow-up to @fabio-zadrozny answer.

Here is a mixin I've created that my class (which gets callbacks from a C-thread) inherits from.

class TracingMixing(object):
    """The callbacks in the FUSE Filesystem are C threads and breakpoints don't work normally.
       This mixin adds callbacks to every function call so that we can breakpoint them."""

    def __call__(self, op, path, *args):
        pydevd.settrace(suspend=False, trace_only_current_thread=True, patch_multiprocessing=True)
        return getattr(self, op)(path, *args)
like image 26
Setheron Avatar answered Nov 03 '22 01:11

Setheron