遠程調試你的 Python 代碼

TangelaHkc 8年前發布 | 40K 次閱讀 Python Python開發

雖然我之前一直自稱「Python 汪」,但是實際上我并沒有在生產環境中大規模使用 Python 的經驗,更多的是用 Python 來處理日常生活中的數據處理、自動化等需求。

幾個月前我加入了一個除了 Java 之外還大量使用 Python、Erlang,少量使用 Golang 的團隊,甚至 Python 在團隊中的地位要高于 Java。于是我終于成了名副其實的 Python 汪。

Careers

目前我所在的技術團隊是「阿里云 云數據庫 服務團隊」,我們正在尋找優秀的資深工程師以及技術專家。如果你有數據庫、云計算等方面的工作經驗,或者在 Python、Java 等語言上有一定的造詣,而且愿意在云數據庫平臺領域做點事情,那么,我很期待你的 來信

Exchange

目前我手上有一批看完之后閑置的實體書,如果你正好也有閑置中的實體書,我們或許可以做個交換 :)

自從我主要使用 Python 進行開發之后,還是很懷念 Java 的,雖然這么說似乎有點像斯德哥爾摩癥候群,但是仔細想想并不是那么一回事。之所以懷念,是因為我的生產力相對沒有過去用 Java 時那么高了。

說懷念 Java,并不是懷念語言本身,而是懷念一套工具鏈,一個生態。雖然 Python 有 PyCharm 這個強力的 IDE,在寫代碼時給我帶來的速度提升比起 IntelliJ IDEA 不遑多讓,但是在其它方面就力有不逮了。

這次我要說的就是遠程調試,Remote Debug。

在 Java 世界里,遠程調試就像是水和空氣,是一個由 JVM 默認提供,IDE 默認支持的功能。我們只需要在啟動 Java 進程的時候帶上調試參數,指定調試端口,就可以從自己的機器上調試運行在服務器上的進程了。

如果不考慮端口沖突的話,一般我喜歡開啟 8000 端口來遠程調試。更多的時候我們會把調試參數放在測試環境的啟動腳本中,這樣子整個測試集群就處于一個隨時可以遠程調試的狀態。

-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=8000

Python 可就沒有這種福利了,親兒子 CPython 并不支持遠程調試,常見的調試手法是這樣的:

  1. 結束正在運行的 Python 進程
  2. 在代碼入口 import pdb 然后 pdb.set_trace()
  3. 在字符界面調試

現在都已經 2016 年了,還讓開發者用這么原始的手法去調試,為了調試還要改動代碼,真是讓人難以置信呢。號稱優雅的 Python 在調試面前也是狼狽不堪啊,改代碼去調試跟我在代碼里打日志調試有什么區別!

當我在 Google 里搜索 python remote debug 的時候,還是有一些收獲的。PyCharm 商業版集成了一個叫 PyDev 的庫,這個庫為 Python 提供了遠程調試的功能。但是為了開啟遠程調試,我們還是需要改動代碼,在代碼入口處加上類似于 pdb 的引用:

import pydevd
pydevd.settrace(
    '192.168.100.123', 
    port=8000, 
    stdoutToServer=True, 
    stderrToServer=True
)

先不說部署遠程調試需要改動代碼這個不人道的條件,我們就先關注 settrace 方法的四個參數。后兩個說的是把標準輸出和標準錯誤重定向到調試器,但是這個變量名有點深意啊。 stdoutToServer ,這個 server 是誰?我遠程調試的就是一個 Python Server,它要把 stdout 重定向到哪里去?

帶著疑問閱讀 PyCharm 提供的 Remote Debug 文檔之后我發現,這完全和我想象中的 Remote Debug 不一樣!

我想要的 Remote Debug 應該是這樣的:在服務器上啟動的目標進程,除了包含我部署的代碼邏輯,還要做為 debug server 去監聽一個端口;debugger 訪問服務器上目標進程監聽的 debug 端口,通過 socket 和 debug server 交互以獲取必要的信息和下發調試指令,對用戶提供一個友好的圖形界面。

然而 PyDev 和 PyCharm 商業版的組合卻是這樣:PyCharm debugger 自身做為 debug server,監聽一個端口;目標進程做為 debug client,訪問 PyCharm 上的 debug server 等待指令。

如果我們需要調試的只是一臺機器上的一個進程,PyCharm 的這種遠程調試方法還是能工作的,雖然有點麻煩,比如目標進程啟動時會主動連接 PyCharm,如果這時候 PyCharm debug server 沒啟動,目標進程就會因為網絡異常而失敗。但是當我們面對的是一個需要調試的集群,這種方式就顯得笨拙而難用了。為了調試整個集群,我需要讓每臺上的每個目標進程都同時連接到我的 PyCharm 上,然后同時開多個調試器。

如果和同事配合調試,還得提前規劃好我調試這幾個進程,你調試那幾個進程,如果我想要調試同事正在調試的進程,就得修改服務器上的代碼然后重啟進程。

這種糟糕的調試體驗,光是想想就害怕了。

雖然關于 Python 遠程調試的搜索結果里,幾乎全是 PyCharm 提供的不合理的方案,但是我還是找到了我想要的東西。微軟提供了一個叫做 ptvsd 的庫,可以在 https://pypi.python.org/pypi/ptvsd 獲取。

微軟不知啥時候搞了個黑科技,為 Visual Studio 添加了 Python 支持,然后 Visual Studio 做為「世界上最好的 IDE」,支持科學的遠程調試自然是義不容辭,于是就有了這個 pvstd,做為一個 debug server 嵌入到目標 Python 進程中,然后 Visual Studio 做為 debugger,主動連到 debug server 上。

雖然我并不可能使用 Visual Studio 去寫 Python,但是這個發現為我打開了新世界的大門。原來除了 PyDev,還有其他的 Remote Debug Library!接下來就是驚喜不斷了,除了 Visual Studio 這個重量級的 IDE,微軟還搞了一個開源的文本編輯器 Visual Studio Code,它也支持 Python 的遠程調試,用的也是 ptvsd。

只要我們配置了正確的 site-package 路徑,讓本地的 Visual Studio Code 能把服務器上正在運行的代碼和本地的代碼配對,就可以開心的調試了,不僅可以調試自己的代碼,還能調試標準庫和第三方庫。

這樣子一來我們即使面對一個需要調試的集群,也可以輕松應對,和同事一起調試也不需要頻繁重啟目標進程修改代碼了~

雖然我現在開發 Python 的時候還是離不開 PyCharm 的幫助,如果沒有 PyCharm,我也許會迷失在一個幾十萬行代碼的 Python 工程中。但是不得不承認,在遠程調試這個殺手級特性上,PyCharm 輸了。

不過 PyCharm 不是沒有完全機會,它可以站在微軟的肩膀上,增加一個調試模式,支持 ptvsd 做為 Debug Server,PyCharm 做為 Debug Client 就好 :)

到目前為止,無論用 PyCharm 也好,VS Code 也好,要想在目標 Python 進程上開啟調試模式,都是需要修改代碼,在入口處添加對調試類庫的引用和初始化的。

下一次,我將分享如何在不改動一行系統代碼的情況下,實現開啟調試、關閉調試。當然,無論如何,重啟進程還是需要的,畢竟就連 Java 的遠程調試,也需要重啟進程才能開啟和關閉不是嗎?

 

來自: http://blog.jamespan.me/2016/06/09/remote-debug-your-python-code/

 

 本文由用戶 TangelaHkc 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!