from
這幾天一直在查乙個線上程式 hang 住的問題. 這個程式總是在執行50分鐘後 hang 住, 通過以下的一些除錯手段,發現是打日誌的時候因為 buffer 滿被 block 了.
python 日誌是預設打到 stderr 的, 無論日誌級別. 而我這個程式是被另乙個程式調起的, 父程序沒有接收子程序的 stderr, 導致了 buffer 被打滿.
在除錯的過程中, 用到了以下幾種 python 除錯手段, 於是記錄以下.
gdb是乙個廣為人知的偵錯程式, 而且線上可用, 非常贊. 但是預設配置的 gdb 並不能列印 python 當前呼叫棧. 我們需要對其做些配置.
首先進行gdb的安裝, 需要gdb7以上版本
sudo yum install gdb python-debuginfo
對於乙個線上已經hang住的程式來說, 可以用gdb -p pid
的形式進行 attach, 列印出當前呼叫棧.
一般來說, 必須是帶debug symbol
的python 編譯版本才能列印出足夠多的資訊, 但是線上的 python 版本往往是不帶debug symbol
的, 於是我們要修改下上述的配置檔案
<<<< if $pc > pyeval_evalframeex && $pc < pyeval_evalcodeex
>>>> if $pc > pyeval_evalframeex && $pc < pyeval_evalcodeex && $fp != 0
對~/.gdbinit
進行上述修改, 即可成功列印出當前 hang住程序的呼叫棧.
具體到我這次遇到的問題, 在打出呼叫棧後發現是卡死在 log 模組的 emit 上, 於是 strace 下看到果然是卡死在 write 的系統呼叫上, 順利找到了原因.
更多的用法可以看 不過大部分的用法依然需要debug symbol
, 按照 wiki 來,不一定可以順利實現.
pdb是 python 自帶的乙個除錯模組. 可以以python -m pdf ***.py
的形式, 以除錯模式啟動乙個 python 程序.
雖然似乎不能 attach 到已執行的程序上, 但是提供了乙個簡單快速的除錯方式.
上述的方式都是不需要侵入**的, 這裡再提供一種侵入**的方式.
import code, traceback, signal
def debug(sig, frame):
"""interrupt running process, and provide a python prompt for
interactive debugging."""
d= # allow access to frame object.
d.update(frame.f_globals) # unless shadowed by global
d.update(frame.f_locals)
i = code.interactiveconsole(d)
message = "signal received : entering python shell.\ntraceback:\n"
message += ''.join(traceback.format_stack(frame))
i.interact(message)
def listen():
signal.signal(signal.sigusr1, debug) # register handler
基本原理是給sigusr1
訊號加上乙個handler, handler 執行時會把當前的變數載入到乙個互動式視窗, 然後開啟互動式console, 接下來就像開啟乙個 repl 一樣了, 可以檢視當前的變數值, 可以改變變數值, 可以呼叫函式看看結果是什麼, 檢視完後^d
離開, 就可以讓程式繼續執行下去.
在加好 handler 後, 我們可以用os.kill(pid, signal.sigusr1)
的方式, 調起 handler, 進行除錯.
值得注意的是, 由於和console 的互動需要 stdout 的支援, 而父子程序預設是不共享 stdout 的,所以當要除錯子程序的時候, 需要重定向子程序的 stdout 到父程序的 stdout, 這個很簡單,就不貼**了.
python除錯方法
最簡單print 只是影響 美觀,而且需要在後面刪掉,比較麻煩 凡是用print來輔助檢視的地方,都可以用斷言 assert 來替代 err.py deffoo s n int s assert n 0,n is zero return 10 n defmain foo 0 可以通過 0 引數來關閉...
python 除錯方法
一 使用pdb 二 使用gdb需首先配置gdb pythin支援,步驟如下 1 修改python 2.6 misc gdbinit,將 while i f f nlocals修改為 while i f f code co nlocals2 在檔案 gdbinit中,加入如下內容 source pyt...
python除錯方法
之前除錯python程式都是用print引數,感覺有點弱爆啊,最近發現python也有類似c語言gdb的工具pdb,記錄下pdb的使用方法和心得。先找了段簡單的測試程式 複製 from ftplib import ftp import sys import socket import pdb def...