聚合国内IT技术精华文章,分享IT技术精华,帮助IT从业人士成长

如何查看一个Python进程在"干什么": py-spy 来帮忙

2019-11-12 23:25 浏览: 3952781 次 我要评论(0 条) 字号:

转载需注明出处:https://www.codelast.com/

如果你觉得一个运行中的Python程序有问题,例如它的耗时比你预想的要长很多,那么你可能会想知道它到底在“干什么”,有很多方法可以实现这个目的,但是很多都是需要修改Python代码来配合的,这显然是让人最不爽的方式。
而 py-spy 这个工具提供了一种无侵入的方式来达成这个目的:

py-spy是Python程序的采样分析器。 它使你可以直观地看到Python程序花费的时间,而无需重新启动程序或以任何方式修改代码。 py-spy的开销非常低:为了提高速度,它是用Rust编写的,并且它与被分析的Python程序不在同一进程中运行。 这意味着py-spy可以安全地用于生产环境的Python代码。


py-spy 的工作原理:在Linux上使用process_vm_readv系统调用,在OSX上使用vm_read,在Windows上使用ReadProcessMemory来直接读取Python程序的内存。

下面就来看看怎么把 py-spy 用起来。
环境:Ubuntu 16.04 LTS,Python 3.6.9

▶ 安装 py-spy
最简单的方法是用 pip 安装:

pip install py-spy

但对我来说,我是在Anaconda环境下使用Python,所以我不想这样干。Anaconda cloud上面没有Linux版的 py-spy,于是我最省力的办法,就是用Rust的包管理工具 Cargo 来安装 py-spy 了。
文章来源:https://www.codelast.com/
首先安装Rust:

curl https://sh.rustup.rs -sSf | bash

这样 Rust 就被安装到了当前用户的 .cargo 目录下。
再修改 .bashrc,把Cargo添加到PATH中:

export RUST_HOME=/home/codelast/.cargo
export PATH=$RUST_HOME/bin:$PATH

现在事情就变得无比简单了,安装 py-spy:

cargo install py-spy

如果执行这个命令出错,提示:

error: linking with `cc` failed: exit code: 1
  |
  (...中间省略...)
  = note: /usr/bin/ld: cannot find -lunwind
          /usr/bin/ld: cannot find -lunwind-ptrace
          /usr/bin/ld: cannot find -lunwind-x86_64
          collect2: error: ld returned 1 exit status
          
 
error: aborting due to previous error
 
error: failed to compile `py-spy v0.3.0`, intermediate artifacts can be found at `/tmp/cargo-installZWBhFq`
 
Caused by:
  could not compile `py-spy`.
那么你可以尝试先安装这个package再重试:
sudo apt install libunwind-dev
文章来源:https://www.codelast.com/
▶ 使用 py-spy
首先启动一个Python程序,用 ps -ef 找到它的 pid,然后就可以用 py-spy 来“监控”它了:
py-spy top --pid 1780
这里 1780 是我的Python进程 pid。不出意外的话,马上会报错:
Permission Denied: Try running again with elevated permissions by going 'sudo env "PATH=$PATH" !!'
按照上面的提示,执行以下命令并输入sudo的密码:
sudo env "PATH=$PATH" !!
注意:那两个感叹号也是命令的一部分,不要觉得奇怪。
现在你会看到类似于 Linux top 命令的输出:
py-spy top
你可以从中找到每个函数的执行时间。
文章来源:https://www.codelast.com/
或者你想要酷炫一点的结果,可以生成火焰图:
py-spy record -o profile.svg --pid 1780
这里也会像上面一样提示没权限,同理,按提示执行上面同样的 sudo 命令,再等待一定的时间之后 Ctrl+C 中断掉,就会生成一张图片 profile.svg:
py-spy record profile
图片从上到下,标识了函数调用栈,X轴则表示函数的执行时间长短(颜色深浅不代表任何问题),越长的,表明该函数执行时间越长,这对性能分析很有用。
文章来源:https://www.codelast.com/
而且更酷的是,如果你把生成的 svg 图片拉到一个浏览器窗口里查看,会发现它是“可点击”的,如果你把鼠标悬停在图片上,就会看到像上图一样的 tip 提示,在左下角还会显示出有当前鼠标指向的这个函数的统计信息,如果你不是悬停,而是点击这个函数所在的矩形区域,则会放大这个函数其下的区域,像极了一个可以导航的网页:
py-spy profile
在放大状态下,点击左上角的“Reset Zoom”就可以回到初始的未缩放状态。是不是很爽!

py-spy 还有更多强大功能,请到其主页去进一步探索。



网友评论已有0条评论, 我也要评论

发表评论

*

* (保密)

Ctrl+Enter 快捷回复