在 Python 中使用 GDB 来调试 转载
2013/11/01 | Comments
大约一年前,我接触了 Java 中的 Btrace 能够不停机查看线上 JVM 运行情况的特性让我艳羡不已。 另外还有强悍的 jStack 和 jConsole 来进行运行期侦测,JVM 的工业级强度果然不是盖的。
当时公司技术方面也遇到了一些瓶颈,一部分原因是 CPython 本身的 IO 模型问题, 另一方面也和早期代码写的极不工整脱不了关系。万般无奈之下,我们用 Jython 推翻重做了主要业务,效果立竿见影,但同时也把真实问题给规避掉了。
在这之后我们在 JVM 的领导下,走上了康庄大道。但我心中始终还有一个梗, 就是想对性能遇到瓶颈的 Python Process 进行线上侦测。 这篇文章就是开始的第一步。
PS:这篇文章理论上是可行的,但是在我机器(Ubuntu 12.04 / 系统自带 Python) 无法正常执行,会爆出 unable to read python frame information 的问题。解决方法我会在下篇文章中写出。这里只是单纯翻译一下原文。
原文可以移步 https://wiki.python.org/moin/DebuggingWithGdb。
有一些类型的 bugs 很难使用 Python 直接进行 debug,比如
- 段错误(无法被捕捉的 Python 异常)
- 卡住的进程(这种情况下面没法使用
pdb来进行跟踪) - 控制之外的后台处理 daemon 进程
这些情况下,你可以使用尝试使用 gdb。
准备
需要在系统安装 gdb 和 Python debug 扩展。 Python debug 扩展包含了一些 debug 命令,并且添加了一些 Python 特定的命令到 gdb。 在主流的 Linux 发行版中,你可以轻松的安装他们:
Fedora:
1 |
|
Ubunt:
1 |
|
在一些老系统上面,也一样可以使用 gdb,具体看文章末尾。
使用 GDB
有两种可行的方法:
- 一开始就使用
gdb来启动应用 - 连接到一个已经运行的 Python 进程
在 gdb 下面启动 Python 同样有两种方式:
交互式:
1 |
|
自动:
1 |
|
这样的话,它会一直运行直到退出、段错误、或者人为的停止(使用 Ctrl+C)。
如果进程已经开始运行,你可以通过 PID 来接入它:
1 |
|
调试进程
如果你的程序段错误了, gdb 会自动暂停程序,这样你可以切换到 gdb 命令行来检查状态。你也可以人为地使用 Ctrl+C 来暂停程序运行。
查看 EasierPythonDebugging 获得 gdb 里面的 Python 命令列表。
查看 C 调用栈
如果你在 debug 段错误,你最想做的可能就是查看 C 调用栈。
在 gdb 的命令行里面,只要运行一下命令:
1 |
|
运气好的话,你可以直接看到问题出现在什么地方。如果它提供的信息不能直接帮你解决问题, 你可以尝试继续追踪调用栈。 调式的结果取决于 debug 信息的有效程度。
查看 Python 调用栈
如果你安装了 Python 扩展,你可以使用
1 |
|
可以获取熟悉的 Python 源代码。
对挂住的进程开刀
如果一个进程看上去挂住了,他可能在等待什么东西(比如锁、IO 等等)。 也有可能在拼命的跑循环。连接上这个进程,然后检查调用栈也许可以帮上忙。
如果进程在疯狂循环,你可以先让它运行一会,使用 cont 命令, 然后使用 Ctrl+C 来暂停,并且打印出调用栈。
如果一些线程卡住了,下面的命令可能会帮上忙:
1 |
|
当前运行的线程被标记为 *,要查看 Python 代码运行到哪里,使用 py-list 查看:
1 |
|
查看所有进程的 Python 代码位置,可以使用:
“` (gdb) thread apply all py-list … 200 201 def accept(self):
202 sock, addr = self.sock.accept() 203 return socketobject(sock=sock), addr 204 accept.doc = realsocket.accept.doc 205 206 def dup(self): 207 “”“dup() -> socket object
Thread 35 (Thread 0xa0bfdb40 (LWP 17911)): Unable to locate python frame
Thread 34 (Thread 0xa13feb40 (LWP 17910)): 197 for method in delegate_methods: 198 setattr(self, method, dummy) 199 close.doc = realsocket.close.doc 200 201 def accept(self):
202 sock, addr = self.sock.accept() 203 return socketobject(_sock=sock), addr …
1 |
|
(gdb) pystack
1 |
|
(gdb) pystackv “`
更多 gdbinit 里面没定义的有用的脚本可以在这里找到:
http://web.archive.org/web/20070915134837/http://www.mashebali.com/?Python_GDB_macros:The_Macros
版权所有 © 2010 转载本站文章请注明: 转载自 Log4D
原文链接: http://blog.log4d.com/2013/11/python-gdb/
您可以随意地转载本站的文章,但是必须在醒目位置注明来源及本站链接,不可以将本站文章商业化使用,或者修改、转换或者以本作品为基础进行创作。
3a1ff193cee606bd1e2ea554a16353ee
在 Python 中使用 GDB 来调试 转载的更多相关文章
- Python中super的用法【转载】
Python中super的用法[转载] 转载dxk_093812 最后发布于2019-02-17 20:12:18 阅读数 1143 收藏 展开 转载自 Python面向对象中super用法与MRO ...
- python中重要的模块--asyncio 转载
转载自: https://www.cnblogs.com/zhaof/p/8490045.html 一直对asyncio这个库比较感兴趣,毕竟这是官网也非常推荐的一个实现高并发的一个模块,python ...
- Visual Studio 2015中使用gdb远程调试linux程序
VS的debug功能非常强大,相比而言linux上的图形化调试一直不是很好用. 如果可以使用VS来调试linux程序,应该是一件比较愉快的事情. 这在2015中变得可能,因为从2015开始VS支持An ...
- Python 中的垃圾回收机制(转载)
from: https://foofish.net/python-gc.html GC作为现代编程语言的自动内存管理机制,专注于两件事:1. 找到内存中无用的垃圾资源 2. 清除这些垃圾并把内存让出来 ...
- vi/vim使用进阶: 在VIM中使用GDB调试 – 使用vimgdb
vi/vim使用进阶: 在VIM中使用GDB调试 – 使用vimgdb << 返回vim使用进阶: 目录 本节所用命令的帮助入口: :help vimgdb 在UNIX系统最初设计时,有一 ...
- gdb可以调试python的pdb么
1.如题: gdb可以调试python的pdb么? 答案:可以,实验如下. 2.实验: 生成一个a.py代码文件,代码如下: import pdb a = 1 print "111" ...
- 【转载】关于Python中的yield
在介绍yield前有必要先说明下Python中的迭代器(iterator)和生成器(constructor). 一.迭代器(iterator) 在Python中,for循环可以用于Python中的任何 ...
- 【转载】Python中如何高效实现两个字典合并,三种方法比较。
本文转载自:http://www.pythoner.com/13.html Python中将两个字典进行合并操作,是一个比较常见的问题.本文将介绍几种实现两个字典合并的方案,并对其进行比较. 对于这个 ...
- 转载:Python中的new style class机制实现
1.Python中的对象模型python中所有东西都是对象 class对象:表示Python内置的类型和定义的类型instance对象(实例对象):表示由class对象创建的实例 1.1 对象间的关系 ...
随机推荐
- HDU--4764
题目: Stone 原题链接:http://acm.hdu.edu.cn/showproblem.php?pid=4764 #include<iostream> #include<c ...
- Netlink 介绍(译)
原文地址:http://people.redhat.com/nhorman/papers/netlink.pdf 译文: 1 介绍 在Linux和Unix的众多发行版中的网络配置功能, 都是编程者事后 ...
- 在阿里云上无法使用mailx发送邮件的解决办法,验证可用。
由于阿里云已将25端口封了(改用465端口),所以在ECS上往外发邮件时要作相应的配置才行. 使用的是163的企业邮箱,笔记简洁可用. 在阿里云的“安全组”开放645端口通行. 1.安装相应软件包: ...
- Python【pymysql】模块
import pymysql# 1.连上数据库 账号.密码 ip 端口号 数据库#2.建立游标#3.执行sql#4 .获取结果# 5.关闭游标#6.连接关闭coon = pymysql.connect ...
- Docker简介与安装配置
目录 Docker简介 什么是Docker 为啥要用容器 Docker Engine Docker架构说明 Docker安装 Docker版本介绍 Ubuntu安装docker-ce CentOS7安 ...
- P2042 [NOI2005]维护数列 && Splay区间操作(四)
到这里 \(A\) 了这题, \(Splay\) 就能算入好门了吧. 今天是个特殊的日子, \(NOI\) 出成绩, 大佬 \(Cu\) 不敢相信这一切这么快, 一下子机房就只剩我和 \(zrs\) ...
- python中的常用模块
python中常用的模块 time: 1)time.localtime([secs]):将一个时间戳转换为当前时区的struct_time.secs参数未提供,则以当前时间为准. 2)time.gmt ...
- Mongodb 笔记03 查询、索引
查询 1. MongoDB使用find来进行查询.find的第一个参数决定了要返回哪些文档,这个参数是一个文档,用于指定查询条件.空的查询会匹配集合的全部内容.要是不指定查询,默认是{}. 2. 可以 ...
- mysql 主从配置(master/slave)
1. 在每台服务器上创建复制账号(也可以只在master上创建用户,这里配置两个是为了方便以后切换) 备库运行的I/O县城需要建立一个到主库的TCP/IP连接,所以必须在主库创建一个用户,并赋予合适 ...
- Vue 嵌套数组 数组更新视图不更新
关于Vue的响应式原理,可以看官方文档或其他资料, https://www.jianshu.com/p/34de360d6035 data里定义了一个数组arr,数组的元素可以是同样格式的数组arrC ...