调试:使用gdb逐句通过Python脚本? [英] Debugging: stepping through Python script using gdb?

查看:191
本文介绍了调试:使用gdb逐句通过Python脚本?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

  printInitializing.... 
a = 10
print变量值是%d%(a)
print全部完成!

...然后说,我想通过在 a = 10 ,然后单步执行脚本。



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



问题是: gdb 本身并不能真正识别放在Python脚本行上的断点:

  $ gdb python 
GNU gdb(GDB)7.3.50.20110806-cvs
...
读取/usr/bin/python...中的符号(不包含找到的调试符号)。 ..done。
(gdb)b test.py:3
没有加载符号表。使用文件命令。
在将来的共享库加载时使断点处于待处理状态? (y或[n])y

断点1(test.py:3)正在等待。
(gdb)run test.py
启动程序:/ usr / bin / python test.py
...

......而整个Python脚本确实在 gdb 内运行,断点根本就没有达到。

所以 - 我想要做的是尽可能地用 gdb ;如果不是,我还有什么其他的选择可以用于类似的事情?

解决方案

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

  import os 
导入信号

PID = os.getpid()

def do_nothing(* args):
通过

def foo():
printInitializing ...
a = 10
os.kill(PID,signal.SIGUSR1)
print变量值为%d%(a)
print 全做完了!

signal.signal(signal.SIGUSR1,do_nothing)

foo()

然后你可以在gdb下运行它:


$ b

  $ gdb  - -args python signal_test.py 
GNU gdb(GDB)红帽企业Linux(7.0.1-37.el5_7.1)
版权所有(C)2009自由软件基金会,Inc.
许可GPLv3 +:GNU GPL版本3或更高版本< http://gnu.org/licenses/gpl.html>
这是免费软件:您可以自由更改和重新分配它。
在法律允许的范围内,不存在任何担保。有关详细信息,请键入显示复制
和显示保修。
这个GDB被配置为x86_64-redhat-linux-gnu。
有关错误报告的说明,请参阅:
< http://www.gnu.org/software/gdb/bugs/> ...
从/ net / gs读取符号/vol3/software/modules-sw/python/2.7/Linux/RHEL5/x86_64/bin/python...done。

当您运行它时,它将一直持续到您呼叫 kill()

 (gdb)run 
启动程序:/net/gs/vol3/software/modules-sw/python/2.7/Linux/RHEL5/x86_64/bin/python signal_test.py
警告:在已添加的符号文件系统中找不到可加载部分DSO at 0x2aaaaaaab000
[使用libthread_db启用线程调试]
初始化...

编程接收到的信号SIGUSR1,用户定义信号1.
0x0000003d340306f7 in kill()from /lib64/libc.so.6

然后您可以查看回溯:

$从/lib64/libc.so.6开始,kill()中返回
#0 0x0000003d340306f7(

  
#1 0x00000000004d82dd in posix_kill(self =< value optimized out>,args =< value optimized out>)
at ./Modules/posixmodule.c:4047
#2 0x000000000049b574 in call_func在python / ceval.c:4012
#3 PyEval_EvalFrameEx(f = 0x8aca30,throwflag =<优化值超出>)时,
(f = 0x8aca30,throwflag =< value out out> /ceval.c:2665 $ b $##4 0x000000000049c5cd在call_function(f = 0x8ac560,throwflag =<值优化出>)
在Python / ceval.c:4098
#5 PyEval_EvalFrameEx(f在pyEval_EvalCodeEx(co = 0x2aaaae224f30,globals =<优化值out> ;,
locals =<)中,Python / ceval.c:2665
#6 0x000000000049d3bb处的值= 0x8ac560,throwflag =< value optimized out> Python / ceval.c:3252
; args = 0x0,argcount = 0,kws = 0x0,kwcount = 0,defs = 0x0,defcount = 0,
closure = 0x0) #7 0x000000000049d432在Python / ceval.c:666
#8 0x00000000004bf321在run_mod(fp = 0x89ad60,filename = 0x7fffffffb5b4signal_test.py,$)中的PyEval_EvalCode(co = 0x1a48,globals = 0xa,locals = 0x0) b $ b start =<优化值out>,globals = 0x7e4680,locals = 0x7e4680,closeit = 1,flags = 0x7fffffffaee0)
在Python / pythonrun.c:1346
#9 PyRun_FileExFlags(fp = 0x89ad60,filename = 0x7fffffffb5b4signal_test.py,
start =<优化值out> ;, globals = 0x7e4680, Python中的
:1332
#10 PyRun_SimpleFileExFlags中的0x00000000004bf5d8(fp =<优化后的值>,
文件名称= 0x7fffffffb5b4 pythonrun.c中的
:936
#11 Py_Main中的0x00000000004148cc(argc =<优化值out>,argv =< value优化出>)
在Modules / main.c:599
#12 0x0000003d3401d994在__libc_start_main()from /lib64/libc.so.6
#13 0x0000000000413b19 in _start()

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

 (gdb)continue 
继续。
变量值为10
全部完成!

程序正常退出。

然而,您可以在适当的框架中逐步浏览,直到找到您感兴趣的语句。你可能会想为此运行一个调试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!"

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

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)

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
...

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

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

解决方案

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()

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.

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

You can then look at a backtrace:

(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.

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脚本?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆