我正在尝试在多线程 Python 应用程序锁定后调试死锁。有没有办法附加调试器来检查进程的状态?
编辑:我正在 Linux 上尝试这个,但如果有一个跨平台的解决方案会很棒。毕竟是 Python :)
使用Winpdb。它是一个独立于平台的图形 GPL Python 调试器,支持通过网络进行远程调试、多线程、命名空间修改、嵌入式调试、加密通信,并且比 pdb 快 20 倍。
特征:
(来源:winpdb.org)
您可以将调试器附加到多线程 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在他的博客上有一些例子。
祝你好运。
(Dan 的博客为我提供了一些关键信息,尤其是线程修复!)
如果你的意思是 pydb,没有办法做到这一点。在这个方向上做了一些努力: 见 svn commit,但它被放弃了。据说winpdb支持它。
我在 PyDev(Windows XP 上的 Eclipse)中调试多线程程序的经验是,无法挂钩使用 thread.start_new_thread 创建的线程,但可以挂钩使用 threading.Thread 创建的线程。希望信息对您有所帮助。
你在什么平台上尝试这个?大多数调试器允许您使用进程 ID 附加到正在运行的进程。您可以通过日志记录或使用任务管理器之类的工具输出进程 ID。一旦实现了这一点,就可以检查各个线程及其调用堆栈。
编辑:我对跨平台的 GNU 调试器 (GDB) 没有任何经验,但是我找到了这个链接,它可能会让你走上正确的道路。它解释了如何添加调试符号(便于读取堆栈跟踪)以及如何指示 gdb 附加到正在运行的 python 进程。
pdbinject允许您将 pdb 注入到已经运行的 python 进程中。
pdbinject 可执行文件只能在 python2 下运行,但也可以很好地注入到 python3 中。
PyCharm IDE从 4.0 版开始允许附加到正在运行的 Python 进程。
这里描述了如何做到这一点。
这可以用作一个简单的“远程”调试器:
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 上工作)。