关于调试:有没有办法将调试器附加到多线程Python进程?

Is there a way to attach a debugger to a multi-threaded Python process?

我试图在锁定后修改多线程Python应用程序中的死锁。 有没有办法附加调试器来检查进程的状态?

编辑:我在Linux上尝试这个,但是如果有一个跨平台的解决方案那就太棒了。 毕竟是Python的:)


使用Winpdb。它是一个独立于平台的图形GPL Python调试器,支持通过网络进行远程调试,多线程,命名空间修改,嵌入式调试,加密通信,速度比pdb快20倍。

特征:

  • GPL许可证。 Winpdb是免费软件。
  • 兼容CPython 2.3到2.6和Python 3000
  • 兼容wxPython 2.6到2.8
  • 独立于平台,并在Ubuntu Gutsy和Windows XP上进行了测试。
  • 用户界面:rpdb2是基于控制台的,而winpdb需要wxPython 2.6或更高版本。

Screenshot
(来源:winpdb.org)


是的,gdb适用于较低级别的调试。

您可以使用thread命令更改线程。

例如

1
2
3
4
(gdb) thr 2
[Switching to thread 2 (process 6159 thread 0x3f1b)]
(gdb) backtrace
....

您还可以查看Python特定的调试器,如Winpdb或pydb。两个平台都独立。


您可以将调试器附加到多线程Python进程,但您需要在C级别执行此操作。要了解正在发生的事情,您需要使用符号编译Python解释器。如果你没有,你需要从python.org下载源代码并自己构建:

1
2
3
4
./configure --prefix=/usr/local/pydbg
make OPT=-g
sudo make install
sudo ln -s /usr/local/pydbg/bin/python /usr/local/bin/dbgpy

确保您的工作负载在该版本的解释器上运行。然后,您可以随时使用GDB附加到它。 Python人员在他们的Misc目录中包含了一个示例".gdbinit",它有一些有用的宏。但是对于多线程调试(!)来说它已经崩溃了。你需要替换这样的行

1
while $pc ;lt; Py_Main || $pc ;gt; Py_GetArgcArgv

以下内容:

1
while ($pc ;lt; Py_Main || $pc ;gt; Py_GetArgcArgv) ;; ($pc ;lt; t_bootstrap || $pc ;gt; thread_PyThread_start_new_thread)

否则像pystack这样的命令不会在主线程以外的线程上终止。有了这些东西,你可以做类似的事情

1
2
3
4
5
6
gdb;gt; attach ;lt;PID;gt;
gdb;gt; info threads
gdb;gt; thread ;lt;N;gt;
gdb;gt; bt
gdb;gt; pystack
gdb;gt; detach

看看发生了什么。的种类。

您可以使用"pyo"宏解析对象的内容。克里斯在他的博客上有一些例子。

祝好运。

(为Dan的博客留出了一些重要信息,特别是线程修复!)


我在PyDev(Windows XP上的Eclipse)中调试多线程程序的经验是,使用thread.start_new_thread创建的线程无法挂钩,但是使用threading.Thread创建的线程可以被挂钩。希望这些信息有用。


如果你的意思是pydb,那就没办法了。在这方面做了一些努力:
看到svn提交,但它被放弃了。据说winpdb支持它。


PyCharm IDE允许从4.0版开始附加到正在运行的Python进程。

这里描述了如何做到这一点。


pdbinject允许您将pdb注入已经运行的python进程。

pdbinject可执行文件只能在python2下运行,但也可以注入python3。


您尝试使用什么平台?大多数调试器允许您使用进程ID附加到正在运行的进程。
您可以通过记录或使用任务管理器等输出进程ID。
一旦实现,就可以检查各个线程及其调用堆栈。

编辑:我没有任何GNU调试器(GDB)的经验,这是跨平台的,但我发现这个链接,它可能会开始你在正确的道路上。它解释了如何添加调试符号(方便读取堆栈跟踪)以及如何指示gdb附加到正在运行的python进程。


推荐阅读