摘要:背景這幾天一直在查一個線上程序住的問題這個程序總是在運行分鐘后住通過以下的一些調試手段發現是打日志的時候因為滿被了日志是默認打到的無論日志級別而我這個程序是被另一個程序調起的父進程沒有接收子進程的導致了被打滿在調試的過程中用到了以下幾種調試
FROM http://kamushin.github.io/debug/python.html
背景這幾天一直在查一個線上程序 hang 住的問題. 這個程序總是在運行50分鐘后 hang 住, 通過以下的一些調試手段,發現是打日志的時候因為 buffer 滿被 block 了.
Python 日志是默認打到 stderr 的, 無論日志級別. 而我這個程序是被另一個程序調起的, 父進程沒有接收子進程的 stderr, 導致了 buffer 被打滿.
在調試的過程中, 用到了以下幾種 Python 調試手段, 于是記錄以下.
GDB是一個廣為人知的調試器, 而且線上可用, 非常贊. 但是默認配置的 GDB 并不能打印 Python 當前調用棧. 我們需要對其做些配置.
首先進行gdb的安裝, 需要gdb7以上版本
sudo yum install gdb python-debuginfo
然后下載這份 gdb 配置文件 http://svn.python.org/projects/python/trunk/Misc/gdbinit 到 ~/.gdbinit
對于一個線上已經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 的系統調用上, 順利找到了原因.
更多的用法可以看https://wiki.python.org/moin/DebuggingWithGdb, 不過大部分的用法依然需要debug symbol, 按照 wiki 來,不一定可以順利實現.
PDB是 Python 自帶的一個調試模塊. 可以以python -m pdf xxx.py 的形式, 以調試模式啟動一個 Python 進程.
雖然似乎不能 attach 到已運行的進程上, 但是提供了一個簡單快速的調試方式.
上述的方式都是不需要侵入代碼的, 這里再提供一種侵入代碼的方式.
import code, traceback, signal def debug(sig, frame): """Interrupt running process, and provide a python prompt for interactive debugging.""" d={"_frame":frame} # 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. Traceback: " 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, 這個很簡單,就不貼代碼了.
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/37948.html
摘要:調試器可幫助程序員分析完整的代碼。我們將使用標準庫中的模塊調試我們的腳本。例外是程序執行期間發生的錯誤。設置斷點并檢查堆棧幀,并列出源代碼。輸入以繼續調試。分析和計時程序分析程序意味著測量程序的執行時間。的模塊用于分析程序。 showImg(https://segmentfault.com/img/remote/1460000018807029?w=902&h=442); 來源 | ...
摘要:通過單元測試,開發者可以為構成程序的每一個元素例如,獨立的函數,方法,類以及模塊編寫一系列獨立的測試用例。在每個測試中,斷言可以用來對不同的條件進行檢查。當退出調試器時,調試器會自動恢復程序的執行。 Python已經演化出了一個廣泛的生態系統,該生態系統能夠讓Python程序員的生活變得更加簡單,減少他們重復造輪的工作。同樣的理念也適用于工具開發者的工作,即便他們開發出的工具并沒有出現...
摘要:安裝一個的版本。選一個的解釋器想要在中運行代碼必須要告訴使用哪個解釋器才行。運行文件最簡單的方法是點擊右鍵選擇在終端運行。然后選擇調試工具欄上的設置圖標。該命令打開一個可用調試器的菜單,顯示和。選擇,這個會創建一個包含許多配置的文件。 開始 安裝 Python extension 。 安裝一個python3的版本。 選一個python的解釋器 想要在vscode中運行python代...
摘要:上一篇文章第三章概念及應用第三節客戶端編程下一篇文章第四章網站部署第二節靜態文件之前著重講解的編程知識點,所有之前的例子都使用最簡單的啟動方式運行。 上一篇文章:Python:Tornado 第三章:HTML5 WebSocket概念及應用:第三節:客戶端編程下一篇文章:Python:Tornado 第四章:Tornado網站部署:第二節:靜態文件 之前著重講解Tornado的編程知...
摘要:最近由于工作關系,開始寫程序,同事有用的,有用的。第一種適合及以上版本,因為在版本起,出現了文件,配置可以寫成用文件啟動程序,實測可以觸發斷點。 最近由于工作關系,開始寫flask web程序,同事有用Vim的,有用PyCharm的。在調研了一通python的編輯器,IDE之后,發現Visual Studio Code相對比較適合我。 VSC有相對較全的功能,比較好看舒服的主題,良好的...
閱讀 2617·2021-11-16 11:40
閱讀 3412·2021-11-08 13:26
閱讀 877·2021-10-28 09:32
閱讀 3535·2021-09-13 10:26
閱讀 809·2019-08-30 15:55
閱讀 783·2019-08-30 15:44
閱讀 1912·2019-08-30 15:44
閱讀 1759·2019-08-30 13:48