當前位置:
首頁 > 知識 > Py-Spy:Python程序的抽樣分析器

Py-Spy:Python程序的抽樣分析器

Py-Spy:Python程序的抽樣分析器

Py-Spy是Python程序的抽樣分析器。 它允許您可視化Python程序正花費時間在哪部分,而無需重新啟動程序或以任何方式修改代碼。 Py-Spy的開銷極低:它使用Rust語言編寫,速度快,不會在與配置的Python程序相同的進程中運行,也不會以任何方式中斷正在運行的程序。 這意味著Py-Spy可以安全地用於生產環境的Python代碼。

Py-Spy適用於Linux,OSX和Windows,並支持分析所有最新版本的CPython解釋器(版本2.3-2.7和3.3-3.7)

安裝

可以從PyPI安裝預構建的二進位wheel格式文件:

Py-Spy:Python程序的抽樣分析器

如果你是Rust用戶,py-spy也可以通過下面方式安裝:

Py-Spy:Python程序的抽樣分析器

用法

py-spy在命令行中工作,並獲取要從中取樣的程序的PID或要運行的python程序的命令行:

Py-Spy:Python程序的抽樣分析器

默認的可視化是python程序的類似top命令輸出的實時視圖:

Py-Spy:Python程序的抽樣分析器

還支持從運行過程生成火焰圖:

Py-Spy:Python程序的抽樣分析器

這將生成一個SVG文件,如下所示:

Py-Spy:Python程序的抽樣分析器

通過將--dump傳遞給命令行,還可以為每個線程轉儲當前的調用堆棧。

經常問的問題

為什麼我們需要另一個Python分析器?

該項目旨在讓您分析和調試任何正在運行的Python程序,即使該程序正在為生產流量提供服務。

雖然還有許多其他python分析項目,但幾乎所有項目都需要以某種方式修改被分析的程序。 通常,分析代碼在目標python進程內部運行,這將減慢並改變程序的運行方式。 這意味著使用這些分析器來調試生產服務中的問題通常不安全,因為它們通常會對性能產生顯著影響。 唯一一個完全在單獨進程中運行的Python探查器是pyflame,它通過使用ptrace系統調用來描述遠程python進程。 雖然pyflame是一個很棒的項目,但它還不支持Python 3.7,並且不適用於OSX或Windows。

py-spy如何運作?

Py-spy通過使用Linux上的process_vm_readv系統調用,OSX上的vm_read調用或Windows上的ReadProcessMemory調用直接讀取python程序的內存。

通過查看全局PyInterpreterState變數來獲取Python程序的調用堆棧,以獲取在解釋器中運行的所有Python線程,然後迭代每個線程中的每個PyFrameObject以獲取調用堆棧。 由於Python ABI在不同版本之間發生變化,我們使用rusts的bindgen為我們關心的每個Python interperator類生成不同的rust結構,並使用這些生成的結構來計算Python程序中的內存布局。

由於地址空間布局隨機化,獲取Python解釋器的內存地址可能有點棘手。 如果目標python解釋器帶有符號,則通過取消引用interp_head或_PyRuntime變數(取決於Python版本),很容易找出解釋器的內存地址。 但是,許多Python版本附帶了剝離的二進位文件,或者在Windows上沒有相應的PDB符號文件。 在這些情況下,我們通過BSS部分掃描看起來像是指向有效PyInterpreterState的地址,並檢查該地址的布局是否符合我們的預期。

py-spy配置文件原生擴展?

由於我們通過查看PyInterpreterState來獲取python程序的調用堆棧,我們還沒有獲得有關非python線程的信息,也無法分析像Cython或C ++等語言編寫的本機擴展。 本機代碼將顯示為在調用本機函數的Python行中花費時間,而不是現在它自己的條目。

應該可以使用libunwind之類的東西來分析Python Extensions中的原生代碼。 如果這是你感興趣的事情,請提出這個問題。

你什麼時候需要以sudo身份運行?

Py-spy通過從不同的python進程讀取內存來工作,出於安全原因,這可能不允許,具體取決於您的操作系統和系統設置。 在許多情況下,以root用戶(使用sudo或類似用戶)運行可以解決這些安全限制。 OSX總是需要以root身份運行,但在Linux上它取決於你如何啟動py-spy和系統安全設置。

在Linux上,默認配置是在附加到非子進程時需要root許可權。 對於py-spy,這意味著您可以通過使用py-spy來創建進程(py-spy -- python myprogram.py)從而不需要root許可權來分析,但通過指定PID附加到現有進程通常需要root(sudo py-spy -pid 123456)。 您可以通過設置ptrace_scope sysctl變數來消除linux對此的限制。

在Kubernetes下運行

py-spy需要SYS_PTRACE才能讀取進程內存。 Kubernetes默認情況下會丟棄該功能,從而導致錯誤

Py-Spy:Python程序的抽樣分析器

處理此問題的推薦方法是編輯規範和所有功能。 對於部署,可以通過將此添加到Deployment.spec.template.spec.containers來完成

Py-Spy:Python程序的抽樣分析器

有關詳細信息,請訪問:https://kubernetes.io/docs/tasks/configure-pod-container/security-context/#set-capabilities-for-a-container

請注意,這將刪除現有的pod並再次創建。

為什麼我在OSX上分析/usr/bin/python時遇到問題?

OSX有一個稱為系統完整性保護的功能,即使root用戶也無法從位於/usr/bin中的任何二進位文件中讀取內存。 不幸的是,這包括了OSX附帶的python解釋器。

有幾種不同的方法可以解決這個問題:

你可以安裝一個不同的Python發行版(你可能想要遠離python2遷移=)

你可以使用virtualenv在SIP不適用的環境中運行系統python。

你可以禁用系統完整性保護。

你是如何通過PyPI分發Rust可執行二進位文件的?

好吧,沒有人真正問過我這個 - 但我想分享,因為這是一個非常可怕的黑科技,可能對其他人有用。

我真的想通過PyPI分發這個軟體包,因為使用pip進行安裝會使大多數Python程序員更容易安裝到他們的系統上。 不幸的是,將可執行文件安裝為python腳本並不是setuptools支持的。

為了解決這個問題,我使用setuptools_rust包來構建py-spy二進位文件,然後重寫distutils install命令將構建的二進位文件複製到python腳本文件夾中。 通過為所支持的平台預先構建的輪子,這意味著我們可以使用pip安裝py-spy,而不需要在安裝它的機器上安裝Rust編譯器。

這是否能在BSD上運行? 支持32位Windows? 與PyPy集成? 使用USC-16版本的Python2?

還沒有=)。

可信度

py-spy受到Julia Evans在rbspy上的出色工作的啟發。 特別是,生成火焰圖的代碼直接來自rbspy,這個項目使用從rbspy中分離出來的(read-process-memory和proc-maps)包。

許可證

Py-spy是在GNU通用公共許可證v3.0下發布的,請參閱LICENSE文件以獲取全文。


英文原文:https://github.com/benfred/py-spy
譯者:趙四妹

喜歡這篇文章嗎?立刻分享出去讓更多人知道吧!

本站內容充實豐富,博大精深,小編精選每日熱門資訊,隨時更新,點擊「搶先收到最新資訊」瀏覽吧!


請您繼續閱讀更多來自 Python部落 的精彩文章:

Jix:在終端中偏要用滑鼠點擊的Git客戶端
在Python中使用Elasticsearch

TAG:Python部落 |