跳转至

使用gdb调试Python程序

使用gdb调试Python程序,最核心的一个使用场景就是长时间运行的Python脚本没有响应了,程序卡住了但是不知道卡在哪里,又不能ctrl c了重新跑, 即需要对正在运行的Python程序进行调试。调试的需求也很简单,其实主要是需要查看当前的运行状态,也就是运行到哪里了,上下文变量的值。gdb常用于 调试C/C++程序,但是gdb也可以调试Python程序,只需要在gdb中加载Python的调试模块即可。

环境配置

apt install gdb python3 python3-dbg
# 要安装对应版本的python-dbg,如python3.8-dbg
写测试代码
import time
def fib(n):
    time.sleep(0.01)
    if n == 1 or n == 0:
        return 1
    for i in range(n):
        return fib(n-1) + fib(n-2)

fib(100)
启动程序
python fib.py &
找到对应的进程号148然后使用gdb连接python进程
gdb python3 148
python3换成实际执行的Python

GNU gdb (Ubuntu 9.2-0ubuntu1~20.04) 9.2
Copyright (C) 2020 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-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
    <http://www.gnu.org/software/gdb/documentation/>.

For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from python3...
Reading symbols from /usr/lib/debug/.build-id/02/526282ea6c4d6eec743ad74a1eeefd035346a3.debug...
Attaching to program: /usr/bin/python3, process 148
Reading symbols from /lib/x86_64-linux-gnu/libc.so.6...
Reading symbols from /usr/lib/debug//lib/x86_64-linux-gnu/libc-2.31.so...
Reading symbols from /lib/x86_64-linux-gnu/libpthread.so.0...
Reading symbols from /usr/lib/debug/.build-id/4f/c5fc33f4429136a494c640b113d76f610e4abc.debug...
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
Reading symbols from /lib/x86_64-linux-gnu/libdl.so.2...
Reading symbols from /usr/lib/debug//lib/x86_64-linux-gnu/libdl-2.31.so...
Reading symbols from /lib/x86_64-linux-gnu/libutil.so.1...
Reading symbols from /usr/lib/debug//lib/x86_64-linux-gnu/libutil-2.31.so...
Reading symbols from /lib/x86_64-linux-gnu/libm.so.6...
Reading symbols from /usr/lib/debug//lib/x86_64-linux-gnu/libm-2.31.so...
Reading symbols from /lib/x86_64-linux-gnu/libexpat.so.1...
(No debugging symbols found in /lib/x86_64-linux-gnu/libexpat.so.1)
Reading symbols from /lib/x86_64-linux-gnu/libz.so.1...
(No debugging symbols found in /lib/x86_64-linux-gnu/libz.so.1)
Reading symbols from /lib64/ld-linux-x86-64.so.2...
(No debugging symbols found in /lib64/ld-linux-x86-64.so.2)
0x00007fec057c10da in __GI___select (nfds=nfds@entry=0, readfds=readfds@entry=0x0, writefds=writefds@entry=0x0, exceptfds=exceptfds@entry=0x0, timeout=timeout@entry=0x7fff99ce33a0) at ../sysdeps/unix/sysv/linux/select.c:41
41  ../sysdeps/unix/sysv/linux/select.c: No such file or directory.
如果所有的symbols都加载了就可以继续调试了,支持以下命令

命令 说明
py-bt 输出Python调用栈
py-bt-full 输出Python调用栈
py-up 在调用栈向上一级
py-down 在调用栈向下一级
py-list 显示代码
py-locals 输出locals变量
py-print 输出
(gdb) py-list
   1    import time
   2    def fib(n):
  >3        time.sleep(0.01)
   4        if n == 1 or n == 0:
   5            return 1
   6        for i in range(n):
   7            return fib(n-1) + fib(n-2)
   8
(gdb) n
4970    in ../Python/ceval.c
(gdb) py-locals
n = 4
(gdb) b
Breakpoint 2 at 0x56acbe: file ../Include/object.h, line 459.
(gdb) c
Continuing.

Breakpoint 2, _PyEval_EvalFrameDefault (f=<optimized out>, throwflag=<optimized out>) at ../Include/object.h:459
459 in ../Include/object.h
... # 省略一些c命令
(gdb) py-locals
n = 3
(gdb) py-bt
Traceback (most recent call first):
  File "fib.py", line 4, in fib
    if n == 1 or n == 0:
  File "fib.py", line 7, in fib
    return fib(n-1) + fib(n-2)
   ... 省略一些输出
(gdb)
(gdb) py-up
#6 Frame 0x7fec0531a580, for file fib.py, line 7, in fib (n=4, i=0)
    return fib(n-1) + fib(n-2)
(gdb) py-locals
n = 4
i = 0
(gdb) py-up
#18 Frame 0x7fec0531c040, for file fib.py, line 7, in fib (n=7, i=0)
    return fib(n-1) + fib(n-2)
(gdb) py-print i
local 'i' = 0
(gdb) py-print n
local 'n' = 7
(gdb) py-down
#12 Frame 0x7fec0531a900, for file fib.py, line 7, in fib (n=6, i=0)
    return fib(n-1) + fib(n-2)
(gdb) py-print n
local 'n' = 6

评论