在Linux下调试Python代码的各类方法

这篇文章主要介绍了在Linux下调试Python代码的各类方法,用于编程后的debug工做,须要的朋友能够参考下node

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

日志ios

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

若是你曾经用print语句来调试代码如今停下吧,用logging.debug替代,开始能够慢慢来,之后彻底禁用它...github

追踪
有时看到程序如何被执行会颇有帮助。你可使用IDE的调试共轭ngn一步一步的运行程序,但你须要知道你要找的是什么,不然这将会是一个漫长的过程。
标准库中有一个 trace模块,能够打印全部执行过程当中的内容(像制做 覆盖率报告)。
 shell

?编程

1服务器

python -mtrace --trace script.py网络

这将产生大量输出(每一个行会被打印输出,因此你最好经过管道,用grep只看本身感兴趣的部分),例如:
 session

?

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

  

...

相关文章
相关标签/搜索