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

时间:2008-09-06 18:14:06

标签: python debugging

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

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

9 个答案:

答案 0 :(得分:14)

使用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

答案 1 :(得分:11)

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

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

e.g

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

您还可以查看特定于Python的调试程序,例如Winpdbpydb。两个平台都独立。

答案 2 :(得分:7)

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

./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”,它有一些有用的宏。但是对于多线程调试(!)来说它已经崩溃了。你需要替换像这样的行

while $pc < Py_Main || $pc > Py_GetArgcArgv

以下内容:

while ($pc < Py_Main || $pc > Py_GetArgcArgv) && ($pc < t_bootstrap || $pc > thread_PyThread_start_new_thread)

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

这样的事情
gdb> attach <PID>
gdb> info threads
gdb> thread <N>
gdb> bt
gdb> pystack
gdb> detach

看看发生了什么。那种。

您可以使用“pyo”宏解析对象的内容。 Chris has some examples在他的博客上。

祝你好运。

(为Dan's blog留出了一些重要信息,特别是线程修复!)

答案 3 :(得分:4)

如果你的意思是pydb,那就没办法了。在这方面做了一些努力: see the svn commit,但它被放弃了。据说是winpdb supports it

答案 4 :(得分:4)

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

答案 5 :(得分:0)

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

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

答案 6 :(得分:0)

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

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

答案 7 :(得分:0)

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

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

答案 8 :(得分:0)

这可以用作简单的“远程”调试器:

import sys
import socket
import pdb

def remote_trace():
    server = socket.socket()
    server.bind(('0.0.0.0', 12345))
    server.listen()
    client, _= server.accept()
    stream = client.makefile('rw')
    sys.stdin = sys.stdout = sys.stderr = stream
    pdb.set_trace()

remote_trace()

# Execute in the shell: `telnet 127.0.0.1 12345`

在Windows上,使用Netcat代替Telnet(在Linux上也可以使用)更容易。