这是一个我用于调试或分析工具概述,不一定是完整全面,如果你知道更好的工具,请在评论处标记。

日志

是的,的确,不得不强调足够的日志记录对应用程序是多么的重要。您应该记录重要的东西,如果你的记录足够好的话,你可以从日志中找出问题从而节省大量的时间。

如果你曾经用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 pdb
pdb.set_trace() # opens up pdb prompt

或者:

1
2
3
4
5
6
7
try:
  code
  that
  fails
except:
  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 rpdb2
rpdb2.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 IPython
IPython.embed()

标准Linux工具

他们未被充分利用很令我惊讶。通过这些工具集你能弄清楚诸如这些的很多问题:从性能问题(太多的系统调用,内存分配等)到死锁,网络,磁盘等问题。

1
2
sudo apt-get install htop
sudo 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-dbg
zcat /usr/share/doc/python2.7/gdbinit.gz > ~/.gdbinit
run app with python2.7-dbg
sudo 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.patch
patch -p1 < python2.7_track_free_list.patch
debuild -us -uc cd ..
sudo dpkg -i python2.7-minimal_2.7*.deb python2.7-dev_*.deb

然后安装pytracemalloc(请注意:如果你是在虚拟环境中做的这些操作,那么在python重新安装后,你需要重建它-仅运行virtualenv myenv即可):

1
pip install pytracemalloc
1
  

现在,你就可以通过以下代码来封装你的应用程序:

1
2
3
4
5
6
7
8
9
10
11
import tracemalloc, time
tracemalloc.enable()
top = tracemalloc.DisplayTop(
  5000, # log the top 5000 locations
  file=open('/tmp/memory-profile-%s' % time.time(), "w")
)
top.show_lineno = True
try:
  # code that needs to be traced
finally:
  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代码的各种方法的更多相关文章

  1. linux下vim python代码自动补全

    一.vim python自动补全插件:pydiction 可以实现下面python代码的自动补全: 1.简单python关键词补全 2.python 函数补全带括号 3.python 模块补全 4.p ...

  2. linux操作系统下调试python代码方法

    一.python有调试工具pdb,可以用来进行代码调试. pdb的常用命令说明: l #查看运行到哪行代码 n #单步运行,跳过函数 s #单步运行,可进入函数 p 变量 #查看变量值 b 行号 #断 ...

  3. linux下 调试C#代码

    参考两位大神的帖子: https://blog.csdn.net/soband_xiang/article/details/82914195 https://blog.csdn.net/weixin_ ...

  4. Linux 下安装python软件包(pip、nose、virtualenv、distribute )

    新手刚开始学习Python,目前学习<笨方法学python>ing- 在学习习题46时需要安装几个软件包:pip.nose.virtualenv.distribute !在此记录Linux ...

  5. linux下配置python环境 django创建helloworld项目

    linux下配置python环境 1.linux下安装python3 a. 准备编译环境(环境如果不对的话,可能遇到各种问题,比如wget无法下载https链接的文件) yum groupinstal ...

  6. linux下搭建python机器学习环境

    前言 在 linux 下搭建 python 机器学习环境还是比较容易的,考虑到包依赖的问题,最好建立一个虚拟环境作为机器学习工作环境,在建立的虚拟环境中,再安装各种需要的包,主要有以下6个(这是看这个 ...

  7. 【转载】PDB命令行调试Python代码

    转载自这里. (博主按:PDB调试python代码和用GDB调试c++代码很类似) 你有多少次陷入不得不更改别人代码的境地?如果你是一个开发团队的一员,那么你遇到上述境地的次数比你想要的还要多.然而, ...

  8. linux下安装python

    在Linux下安装Python的操作相当简单,按如下步骤操作即可: 命令: wget https://www.python.org/ftp/python/3.5.2/Python-3.5.2.tgzt ...

  9. linux下安装python linux下一些常用的命令

    注意 ubuntukylin-14.04.2-desktop-amd64 自带python2.7.6 这个说的比较详细 http://wenku.baidu.com/link?url=gaeFcQrc ...

随机推荐

  1. 【学时总结】◆学时·IX◆ 整体二分

    ◆学时·IX◆ 整体二分 至于我怎么了解到这个算法的……只是因为发现一道题,明显的二分查找,但是时间会爆炸,被逼无奈搜题解……然后就发现了一些东西QwQ ◇ 算法概述 整体二分大概是把BFS与二分查找 ...

  2. MySQL数据库常见报错原因

    1.启动数据库时报错 启动 # /etc/init.d/mysqld start Starting MySQL.Logging to '/application/mysql-5.6.36/data/m ...

  3. Java应用:经纬度匹配(geohash加密)

    本文采用http://gc.ditu.aliyun.com地址进行经纬度匹配,无数量限制 如果给定经纬度进行geohash加密操作,先解密得到相应gps坐标,具体程序如下所示: import java ...

  4. yum方式安装及配置最新的mysql5.7

    1.删除旧版本的MySQL rpm -qa|grep -i mysql 用命令yum -y remove mysql 2.下载新版安装源 下载mysql的repo源 这个安装的mysql5.7.20 ...

  5. Java——Random类随机整数---18.10.11

    一.Random类的定义 1.Random类位于java.util包中,主要用于生成 伪随机数 2.random类将 种子数 作为随机算法的起源数字,计算生成伪随机数,其与生成的随机数字的区间无关 3 ...

  6. EF更新时出错,An error occurred while updating the entries. See the inner exception for details

           在使用EF进行更新数据时出错,报出的异常是 "An error occurred while updating the entries. See the inner excep ...

  7. TensorLayer 中文文档

    TensorLayer 中文文档 好消息 我们获得了 ACM Multimedia (MM) 年度最佳开源软件奖. TensorLayer 是为研究人员和工程师设计的一款基于Google Tensor ...

  8. Linux上Makefile管理java项目

    前面文章讲到了Linux上通过.spec文件与rpmbuild命令将java程序打包为RPM安装包, 现阶段遇到新的需求: 使用Makefile来操纵java的编译.打包 该需求以前面的内容为基础 可 ...

  9. DDD领域驱动设计基本理论知识总结(转)

    领域驱动设计之领域模型 为什么建立一个领域模型是重要的 领域通用语言(UBIQUITOUS LANGUAGE) 将领域模型转换为代码实现的最佳实践 领域建模时思考问题的角度 领域驱动设计的经典分层架构 ...

  10. 「日常训练」Mike and Feet(Codeforces Round #305 Div. 2 D)

    题意 (Codeforces 548D) 对一个有$n$个数的数列,我们要求其连续$x(1\le x\le n)$(对于每个$x$,这样的连续group有若干个)的最小数的最大值. 分析 这是一道用了 ...