web-dev-qa-db-ja.com

デバッグ:gdbを使用してPythonスクリプトをステップ実行しますか?

次の非常に単純なPythonスクリプトがあるとします。

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

...そして、このスクリプトをデバッグするには、a=10行にブレークポイントを設定し、スクリプトをステップ実行します。

共有オブジェクト(.so)ライブラリの一部として含まれる可能性があるPythonバインディングをデバッグしたいので、これにgdbを使用したいと思います。 -したがって、理想的には、ブレークポイントをPythonコード行に配置し、共有オブジェクトのC部分に「ステップイン」します...(DebuggingWithGdb-PythonInfo Wiki は、これが可能であることを明示的に明示していません

問題は次のとおりです。gdb自体は、Pythonスクリプト行に配置されたブレークポイントを実際には認識できません。

$ 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内で実行されますが、ブレークポイントに到達することはありません。

だから-私がやりたいことは、gdbで可能な限りです。そうでない場合は、同様のものに対して他にどのような選択肢がありますか?

27
sdaau

非常に興味深い質問です。これが私のアプローチです。 _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の下で実行できます。

_$ 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()の呼び出しに到達するまで実行されます。

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

続行すると、プログラムの残りの部分は正常に実行されます。

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

Program exited normally.
_

代わりに、興味のあるステートメントに到達するまで、適切なフレームをステップスルーできます。これを理解するには、おそらくPythonのデバッグを実行する必要があります。

26
Michael Hoffman

これは興味深い質問であり、私は他の回答を熱心に待っていますが、今のところ:

ドキュメント http://wiki.python.org/moin/DebuggingWithGdb は主にsegfaultsとハングしたPythonプロセスのデバッグ用であり、Pythonの通常のステップではありませんコード。

あなたの意図を100%理解しているとは思いません。特定のPython行に達したらC(Python C API)コードを中断しますか?それからそれはただ行うことの問題ではないでしょう:

_# some Python code
# some other Python code
myobj.foo()
# some other Python code
_

ここで、myobj.foo()はC APIを呼び出します。次に、_myobj.foo_にアタッチされた関数にブレークポイントを配置するだけで、ブレークポイントが適切な場所に配置されます。より多くの機能が必要ですか、それとも同じことを実現するためのより自然な方法を単に探していますか?

2
Eli Bendersky