调试:使用 gdb 单步执行 Python 脚本?

Debugging: stepping through Python script using gdb?(调试:使用 gdb 单步执行 Python 脚本?)
本文介绍了调试:使用 gdb 单步执行 Python 脚本?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

假设我们有以下超级简单的 Python 脚本:

Let's say we have the following mega-simple Python script:

print "Initializing"....
a=10
print "Variable value is %d" % (a)
print "All done!"

...然后说,我想通过在 a=10 行放置一个断点来调试此脚本,然后单步执行该脚本.

... and say, I'd like to debug this script by placing a breakpoint at line a=10, and then stepping through the script.

现在,我想为此使用 gdb,因为我想调试可能作为共享对象(.so) 库 - 因此,理想情况下,我会在 Python 代码行上放置一个断点,然后进入"共享对象的 C 部分...(请注意,DebuggingWithGdb - PythonInfo Wiki 并没有明确说明这是可能的)

Now, I'd like to use gdb for this, because I'd like to debug Python bindings that may come as a part of a shared object (.so) library - hence, I'd ideally place a breakpoint on a Python code line, and then "step into" the C part of the shared object... (Note that DebuggingWithGdb - PythonInfo Wiki doesn't really explicitly state that this is possible)

问题是:gdb 本身无法真正识别断点,放置在 Python 脚本行:

The problem is: gdb on its own cannot really recognize breakpoints, placed on a Python script line:

$ gdb python
GNU gdb (GDB) 7.3.50.20110806-cvs 
...
Reading symbols from /usr/bin/python...(no debugging symbols found)...done.
(gdb) b test.py:3
No symbol table is loaded.  Use the "file" command.
Make breakpoint pending on future shared library load? (y or [n]) y

Breakpoint 1 (test.py:3) pending.
(gdb) run test.py
Starting program: /usr/bin/python test.py
...

...虽然整个 Python 脚本确实在 gdb 中运行,但根本无法到达断点.

... and while the entire Python script does run within gdb, the breakpoint is simply never reached.

所以 - 是我想要做的,完全可能使用 gdb;如果没有,对于类似的东西,我还有什么其他选择?

So - is what I want to do, at all possible with gdb; and if not, what other alternatives would I have for something similar?

推荐答案

非常有趣的问题.这是我的方法.创建signal_test.py:

Very interesting question. Here's my approach. Create signal_test.py:

import os
import signal

PID = os.getpid()

def do_nothing(*args):
    pass

def foo():
    print "Initializing..."
    a=10
    os.kill(PID, signal.SIGUSR1)
    print "Variable value is %d" % (a)
    print "All done!"

signal.signal(signal.SIGUSR1, do_nothing)

foo()

然后就可以在gdb下运行了:

Then you can run it under gdb:

$ gdb --args python signal_test.py
GNU gdb (GDB) Red Hat Enterprise Linux (7.0.1-37.el5_7.1)
Copyright (C) 2009 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-redhat-linux-gnu".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>...
Reading symbols from /net/gs/vol3/software/modules-sw/python/2.7/Linux/RHEL5/x86_64/bin/python...done.

当你运行它时,它会一直运行到你调用 kill():

And when you run it, it will go until you reach the call to kill():

(gdb) run
Starting program: /net/gs/vol3/software/modules-sw/python/2.7/Linux/RHEL5/x86_64/bin/python signal_test.py
warning: no loadable sections found in added symbol-file system-supplied DSO at 0x2aaaaaaab000
[Thread debugging using libthread_db enabled]
Initializing...

Program received signal SIGUSR1, User defined signal 1.
0x0000003d340306f7 in kill () from /lib64/libc.so.6

然后您可以查看回溯:

(gdb) backtrace
#0  0x0000003d340306f7 in kill () from /lib64/libc.so.6
#1  0x00000000004d82dd in posix_kill (self=<value optimized out>, args=<value optimized out>)
    at ./Modules/posixmodule.c:4047
#2  0x000000000049b574 in call_function (f=0x8aca30, throwflag=<value optimized out>)
    at Python/ceval.c:4012
#3  PyEval_EvalFrameEx (f=0x8aca30, throwflag=<value optimized out>) at Python/ceval.c:2665
#4  0x000000000049c5cd in call_function (f=0x8ac560, throwflag=<value optimized out>)
    at Python/ceval.c:4098
#5  PyEval_EvalFrameEx (f=0x8ac560, throwflag=<value optimized out>) at Python/ceval.c:2665
#6  0x000000000049d3bb in PyEval_EvalCodeEx (co=0x2aaaae224f30, globals=<value optimized out>, 
    locals=<value optimized out>, args=0x0, argcount=0, kws=0x0, kwcount=0, defs=0x0, defcount=0, 
    closure=0x0) at Python/ceval.c:3252
#7  0x000000000049d432 in PyEval_EvalCode (co=0x1a48, globals=0xa, locals=0x0) at Python/ceval.c:666
#8  0x00000000004bf321 in run_mod (fp=0x89ad60, filename=0x7fffffffb5b4 "signal_test.py", 
    start=<value optimized out>, globals=0x7e4680, locals=0x7e4680, closeit=1, flags=0x7fffffffaee0)
    at Python/pythonrun.c:1346
#9  PyRun_FileExFlags (fp=0x89ad60, filename=0x7fffffffb5b4 "signal_test.py", 
    start=<value optimized out>, globals=0x7e4680, locals=0x7e4680, closeit=1, flags=0x7fffffffaee0)
    at Python/pythonrun.c:1332
#10 0x00000000004bf5d8 in PyRun_SimpleFileExFlags (fp=<value optimized out>, 
    filename=0x7fffffffb5b4 "signal_test.py", closeit=1, flags=0x7fffffffaee0)
    at Python/pythonrun.c:936
#11 0x00000000004148cc in Py_Main (argc=<value optimized out>, argv=<value optimized out>)
    at Modules/main.c:599
#12 0x0000003d3401d994 in __libc_start_main () from /lib64/libc.so.6
#13 0x0000000000413b19 in _start ()

如果继续,程序的其余部分将正常运行.

If you continue on, the rest of the program will run normally.

(gdb) continue
Continuing.
Variable value is 10
All done!

Program exited normally.

相反,您可以在适当的框架中单步执行,直到找到您感兴趣的语句.您可能需要运行一个调试 Python 以使其更有意义.

You can, instead, step through in the appropriate frame until you reach the statement you're interested in. You're probably going to want to run a debugging Python for this to make much sense.

这篇关于调试:使用 gdb 单步执行 Python 脚本?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!

本站部分内容来源互联网,如果有图片或者内容侵犯您的权益请联系我们删除!

相关文档推荐

Leetcode 234: Palindrome LinkedList(Leetcode 234:回文链接列表)
How do I read an Excel file directly from Dropbox#39;s API using pandas.read_excel()?(如何使用PANDAS.READ_EXCEL()直接从Dropbox的API读取Excel文件?)
subprocess.Popen tries to write to nonexistent pipe(子进程。打开尝试写入不存在的管道)
I want to realize Popen-code from Windows to Linux:(我想实现从Windows到Linux的POpen-code:)
Reading stdout from a subprocess in real time(实时读取子进程中的标准输出)
How to call type safely on a random file in Python?(如何在Python中安全地调用随机文件上的类型?)