Python 程序的抽样分析器 - Py-Spy
?
From:https://python.freelycode.com/contribution/detail/1320
GitHub 地址:https://github.com/benfred/py-spy
?
?
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 格式文件:pip install py-spy
?
用法
py-spy 在命令行中工作,并獲取要從中取樣的程序的 PID 或要運行的 python 程序的命令行:
默認的可視化是python程序的類似top命令輸出的實時視圖:
?
還支持從運行過程生成火焰圖:
這將生成一個SVG文件,如下所示:
通過將 --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默認情況下會丟棄該功能,從而導致錯誤
處理此問題的推薦方法是編輯規范和所有功能。 對于部署,可以通過將此添加到Deployment.spec.template.spec.containers來完成
有關詳細信息,請訪問: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文件以獲取全文。
?
?
?
?
總結
以上是生活随笔為你收集整理的Python 程序的抽样分析器 - Py-Spy的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: FRIDA - API使用篇:rpc、P
- 下一篇: 小甲鱼 OllyDbg 教程系列 (三)