在Linux下调试Python代码的各种方法
这是一个我用于调试或分析工具概述,不一定是完整全面,如果你知道更好的工具,请在评论处标记。
日志
是的,的确,不得不强调足够的日志记录对应用程序是多么的重要。您应该记录重要的东西,如果你的记录足够好的话,你可以从日志中找出问题从而节省大量的时间。
如果你曾经用print语句来调试代码现在停下吧,用logging.debug替代,开始可以慢慢来,以后完全禁用它...
追踪
有时看到程序如何被执行会很有帮助。你可以使用IDE的调试共轭ngn一步一步的运行程序,但你需要知道你要找的是什么,否则这将会是一个漫长的过程。
标准库中有一个 trace模块,可以打印所有执行过程中的内容(像制作 覆盖率报告)。
|
1
|
python -mtrace --trace script.py |
这将产生大量输出(每个行会被打印输出,所以你最好通过管道,用grep只看自己感兴趣的部分),例如:
|
1
2
|
python -mtrace --trace script.py | egrep '^(mod1.py|mod2.py)'- |
如果你喜欢新特性,那么你可以尝试 smiley - 它可以显示变量内容变化,还可以用它来远程追踪程序。
PDB
|
1
2
|
import pdbpdb.set_trace() # opens up pdb prompt |
或者:
|
1
2
3
4
5
6
7
|
try: code that failsexcept: import pdb pdb.pm() # or pdb.post_mortem() |
或(按键盘C键启动脚本):
|
1
|
python -mpdb script.py |
像在REPL中那样:
- c or continue
- q or quit
- l or list, 在当前界面显示源码
- w or where, 显示回溯
- d or down, 显示回溯的下一界面
- u or up, 显示回溯的上一界面
- <enter>, 重复最后一个命令
- 其他任何东西,在当前界面评估源码 (t还有其他的一些命令)
- corcontinue
- qorquit
- lorlist,显示在当前帧的源
- worwhere,显示回溯
- dordown,下山1帧回溯
- uorup,上升1帧回溯
- 回车,重复最后一个命令
几乎任何东西,评估当前帧的Python代码(还有其他几个命令)
可以替代pdb的:
- ipdb (easy_install ipdb) - 像 ipython (自动补齐, 颜色等)
- pudb (easy_install pudb) - 基于curses (类gui), 浏览源码有很好的表现。
远程 PDB
|
1
|
sudo apt-get install winpdb |
替代 pdb.set_trace():
|
1
2
|
import rpdb2rpdb2.start_embedded_debugger("secretpassword") |
现在运行Winpdb , 输入密码 到 File > Attach。
不喜欢 Winpdb ? 只要通过 TCP运行 PDB
使用下面代码:
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
|
import loggging class Rdb(pdb.Pdb): """ This will run pdb as a ephemeral telnet service. Once you connect no one else can connect. On construction this object will block execution till a client has connected. Based on https://github.com/tamentis/rpdb I think ... To use this:: Rdb(4444).set_trace() Then run: telnet 127.0.0.1 4444 """ def __init__(self, port=0): self.old_stdout = sys.stdout self.old_stdin = sys.stdin self.listen_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) self.listen_socket.bind(('0.0.0.0', port)) if not port: logging.critical("PDB remote session open on: %s", self.listen_socket.getsockname()) print >> sys.__stderr__, "PDB remote session open on:", self.listen_socket.getsockname() sys.stderr.flush() self.listen_socket.listen(1) self.connected_socket, address = self.listen_socket.accept() self.handle = self.connected_socket.makefile('rw') pdb.Pdb.__init__(self, completekey='tab', stdin=self.handle, stdout=self.handle) sys.stdout = sys.stdin = self.handle def do_continue(self, arg): sys.stdout = self.old_stdout sys.stdin = self.old_stdin self.handle.close() self.connected_socket.close() self.listen_socket.close() self.set_continue() return 1 do_c = do_cont = do_continue def set_trace(): """ Opens a remote PDB on first available port. """ rdb = Rdb() rdb.set_trace() |
想要 REPL ? IPython 怎么样?
如果你不需要一个整体的调试器,只要启动IPython用下面的代码:
|
1
2
|
import IPythonIPython.embed() |
标准Linux工具
他们未被充分利用很令我惊讶。通过这些工具集你能弄清楚诸如这些的很多问题:从性能问题(太多的系统调用,内存分配等)到死锁,网络,磁盘等问题。
|
1
2
|
sudo apt-get install htopsudo htop |
最有用的是降权运行strace,只需运行速冻 strace -P 12345 或strace-f 命令参数(-f表示strace分支进程)。 通常有很多的输出,你最好将输出重定向输出到一个文件(命令后添加 &> 文件名)来进行更深入的分析。
然后就是ltrace,它和strace相似不过是通过库调用的,参数基本相同。
lsof可以提供 你看过ltrace/ strace的处理号,这样使用:lsof -P 12345
让跟踪更深点
它很容易使用以及可以做很多事,前提是大家都已经安装了htop!
现在,找你所想的进程,仅仅需要按:
- s 显示系统调用跟踪(strace)
- L 显示库调用跟踪(ltrace)
- l 显示lsof
监视
没有更好的替代品了,服务器持续监视,你曾经是否发现自己使用奇奇怪怪的跟踪方法去找出为什么哪里慢了以及资源怎么被消耗了,那么不要再被iotop, iftop, htop, iostat, vmstat等等烦扰了,赶快使用dstat吧,它可以做大多数上述的提到的工具能做的,而且可以做得更好!
它会以紧凑,时尚的代码着色(亲,不像iostat, vmstat哟)持续显示你的数据,而且你可以一直看到以往的数据(与iftop, iotop, htop不同哟)。
仅仅运行这个:
|
1
|
dstat --cpu --io --mem --net --load --fs --vm --disk-util --disk-tps --freespace --swap --top-io --top-bio-adv |
还有一点就是这里还有更简单的方式来写哟,如shell历史记录(shell history)或则重命名命令(aliases)
GDB
这是一个相当复杂和强大的工具,但我仅仅涉及到基础的东西(设置和基本命令)。
|
1
2
3
4
|
sudo apt-get install gdb python-dbgzcat /usr/share/doc/python2.7/gdbinit.gz > ~/.gdbinitrun app with python2.7-dbgsudo gdb -p 12345 |
现在请使用:
bt- 堆栈轨迹(C 级)
pystack- python 堆栈轨迹,前提是你需要拥有~/.gdbinit 并使用python-dbg
c(继续)
有出现 segfaults 么 ?用 faulthandler !
除了Python 3.3其他的都会出现这个可怕的错误, 回到Python 2.x
只要按照下面来做,你至少会找到一条导致段错误的原因。
|
1
2
|
>>> import faulthandler>>> faulthandler.enable() |
内存泄露
好的,这里有许多工具,其中有一些是专门用于WSGI 应用的,像Dozer,但是我最喜欢的无疑是 objgraph。它是如此惊人的方便和易于使用。它没有与WSGI或任何其他东西继承,所以你需要找到你自己的方式来运行以下代码:
|
1
2
3
4
5
|
>>> import objgraph>>> objs = objgraph.by_type("Request")[:15]>>> objgraph.show_backrefs(objs, max_depth=20, highlight=lambda v: v in objs, filename="/tmp/graph.png")Graph written to /tmp/objgraph-zbdM4z.dot (107 nodes)Image generated as /tmp/graph.png |
你会得到一个像 这样的图表(警告:这个图表非常大)。你也会得到 dot输出。
内存利用
有时你想使用更少的内存。少分配内存通常会使程序运行的更快更好,用户们都喜欢精益求精:)
有许多工具可以拿来使用 [1] ,但在我看来最好的是pytracemalloc - 与其他工具相比较,它的开销很小(不需要依赖于削弱速度的 sys.settrace)并且它的输出非常详尽。令人头疼的是它的配置,因为需要你重编译python,但是spt使其很容易做到。
只要运行以下命令,然后你就可以去买午餐或者做其他事了:
|
1
2
3
4
5
|
apt-get source python2.7 cd python2.7-*wget https://github.com/wyplay/pytracemalloc/raw/master/python2.7_track_free_list.patchpatch -p1 < python2.7_track_free_list.patchdebuild -us -uc cd ..sudo dpkg -i python2.7-minimal_2.7*.deb python2.7-dev_*.deb |
然后安装pytracemalloc(请注意:如果你是在虚拟环境中做的这些操作,那么在python重新安装后,你需要重建它-仅运行virtualenv myenv即可):
现在,你就可以通过以下代码来封装你的应用程序:
|
1
2
3
4
5
6
7
8
9
10
11
|
import tracemalloc, timetracemalloc.enable()top = tracemalloc.DisplayTop( 5000, # log the top 5000 locations file=open('/tmp/memory-profile-%s' % time.time(), "w"))top.show_lineno = Truetry: # code that needs to be tracedfinally: top.display() |
会得到像下面这样的输出:
|
1
2
3
4
5
6
7
8
9
10
11
12
13
|
2013-05-31 18:05:07: Top 5000 allocations per file and line#1: .../site-packages/billiard/_connection.py:198: size=1288 KiB, count=70 (+0), average=18 KiB#2: .../site-packages/billiard/_connection.py:199: size=1288 KiB, count=70 (+0), average=18 KiB#3: .../python2.7/importlib/__init__.py:37: size=459 KiB, count=5958 (+0), average=78 B#4: .../site-packages/amqp/transport.py:232: size=217 KiB, count=6960 (+0), average=32 B#5: .../site-packages/amqp/transport.py:231: size=206 KiB, count=8798 (+0), average=24 B#6: .../site-packages/amqp/serialization.py:210: size=199 KiB, count=822 (+0), average=248 B#7: .../lib/python2.7/socket.py:224: size=179 KiB, count=5947 (+0), average=30 B#8: .../celery/utils/term.py:89: size=172 KiB, count=1953 (+0), average=90 B#9: .../site-packages/kombu/connection.py:281: size=153 KiB, count=2400 (+0), average=65 B#10: .../site-packages/amqp/serialization.py:462: size=147 KiB, count=4704 (+0), average=32 B ... |
在Linux下调试Python代码的各种方法的更多相关文章
- linux下vim python代码自动补全
一.vim python自动补全插件:pydiction 可以实现下面python代码的自动补全: 1.简单python关键词补全 2.python 函数补全带括号 3.python 模块补全 4.p ...
- linux操作系统下调试python代码方法
一.python有调试工具pdb,可以用来进行代码调试. pdb的常用命令说明: l #查看运行到哪行代码 n #单步运行,跳过函数 s #单步运行,可进入函数 p 变量 #查看变量值 b 行号 #断 ...
- linux下 调试C#代码
参考两位大神的帖子: https://blog.csdn.net/soband_xiang/article/details/82914195 https://blog.csdn.net/weixin_ ...
- Linux 下安装python软件包(pip、nose、virtualenv、distribute )
新手刚开始学习Python,目前学习<笨方法学python>ing- 在学习习题46时需要安装几个软件包:pip.nose.virtualenv.distribute !在此记录Linux ...
- linux下配置python环境 django创建helloworld项目
linux下配置python环境 1.linux下安装python3 a. 准备编译环境(环境如果不对的话,可能遇到各种问题,比如wget无法下载https链接的文件) yum groupinstal ...
- linux下搭建python机器学习环境
前言 在 linux 下搭建 python 机器学习环境还是比较容易的,考虑到包依赖的问题,最好建立一个虚拟环境作为机器学习工作环境,在建立的虚拟环境中,再安装各种需要的包,主要有以下6个(这是看这个 ...
- 【转载】PDB命令行调试Python代码
转载自这里. (博主按:PDB调试python代码和用GDB调试c++代码很类似) 你有多少次陷入不得不更改别人代码的境地?如果你是一个开发团队的一员,那么你遇到上述境地的次数比你想要的还要多.然而, ...
- linux下安装python
在Linux下安装Python的操作相当简单,按如下步骤操作即可: 命令: wget https://www.python.org/ftp/python/3.5.2/Python-3.5.2.tgzt ...
- linux下安装python linux下一些常用的命令
注意 ubuntukylin-14.04.2-desktop-amd64 自带python2.7.6 这个说的比较详细 http://wenku.baidu.com/link?url=gaeFcQrc ...
随机推荐
- Python实现trim函数
Python中其实也有类似Java的trim函数的,叫做strip,举例: #!/usr/bin/python # -*- coding: UTF-8 -*- str = "0000000h ...
- JVM 垃圾回收机制和常见算法和 JVM 的内存结构和内存分配(面试题)
一.JVM 垃圾回收机制和常见算法 Sun 公司只定义了垃圾回收机制规则而不局限于其实现算法,因此不同厂商生产的虚拟机采用的算法也不尽相同.GC(Garbage Collector)在回收对象前首先必 ...
- JSP/Servlet开发——第一章 动态网页基础
1.动态网页:在服务端运行的使用程序语言设计的交互网页 : ●动态网站并不是指具有动画功能的网站,而是指网站内容可根据不同情况动态变更的网站(股票网站),一般情况下动态网站通过数据库进行架构. ●动态 ...
- 清除input框的缓存
html <div class="container"> <form class="parent" autocomplete="of ...
- jquery获取周对应的日期
项目中用到按周显示的功能,找了一个,然后自己修改了一下,留着以后用: 这是代码,要是直接显示的话就把第43行去掉就行了,如果想要得到数据按照自己的想法重新渲染就保留43行,直接看51行,52行就是你要 ...
- vi/vim连续注释
知识点: 1-可视块模式方法 2-替换方法 3-自定义快捷键方式 今天刚好重新在linux上手工搭建完Lamp环境,用来下vi操作,一段时间不用就有些生疏了,正好经常要注释,回顾下自己会的方法,小结一 ...
- atlas+mysql部署mysql读写分离
1.atlas 简介 Atlas是由 Qihoo 360公司Web平台部基础架构团队开发维护的一个基于MySQL协议的数据中间层项目.它在MySQL官方推出的MySQL-Proxy 0.8.2版本的基 ...
- COURSES POJ1469(模板)
Description Consider a group of N students and P courses. Each student visits zero, one or more than ...
- shell重温---基础篇(shell数组&数组操作)
上篇博客已经分析重温了shell的运行方式以及其中的变量还有字符串,之后按照套路就是数组方面了,废话不多说,直接进入正题哈.(小白笔记,各位看官勿喷...) bash shell呢,支持一位数 ...
- python2.7入门---Number(数字)
今天咱们来简单分享一下关于python中的一种数据类型和操作方法.费话不多说哈,咱们直接来进行实践加理论.首先,我们要知道,Python Number 数据类型用于存储数.数据类型是不允许改变 ...