导读:本期聚焦于小伙伴创作的《Python代码被卡住怎么调试?利用Py-Spy动态附加到正在运行的进程生成火焰图分析死锁位置》,敬请观看详情,探索知识的价值。以下视频、文章将为您系统阐述其核心内容与价值。如果您觉得《Python代码被卡住怎么调试?利用Py-Spy动态附加到正在运行的进程生成火焰图分析死锁位置》有用,将其分享出去将是对创作者最好的鼓励。

在Python程序运行过程中,有时会遇到进程突然卡住、无响应的情况,这类问题往往出现在多线程或者多进程协作的场景中,尤其是死锁问题,很难通过常规日志快速定位。此时不需要修改代码重启服务,我们可以利用Py-Spy工具动态附加到正在运行的进程,生成火焰图来分析问题根因。

Python代码被卡住怎么调试?利用Py-Spy动态附加到正在运行的进程生成火焰图分析死锁位置

Py-Spy工具简介

Py-Spy是一款开源的Python进程采样分析工具,它的最大特点是支持动态附加到已经运行的Python进程,不需要对目标代码做任何修改,也不会影响进程的正常运行状态。它可以直接读取目标进程的内存信息,采样函数调用栈,最终生成直观的火焰图,帮助开发者快速定位性能瓶颈和阻塞问题。

安装Py-Spy

Py-Spy支持通过pip快速安装,执行以下命令即可完成安装:

pip install py-spy

安装完成后,可以在终端执行py-spy --help验证是否安装成功,正常会输出工具的帮助信息。

动态附加到运行中的Python进程

首先我们需要获取目标Python进程的PID,在Linux或者macOS系统中,可以通过ps命令查找:

ps aux | grep python

假设我们查到的目标进程PID是12345,接下来就可以使用Py-Spy附加到这个进程,执行以下命令开始采样:

py-spy record -o profile.svg --pid 12345

上述命令中,-o参数指定生成的火焰图文件路径,--pid指定目标进程的PID。执行命令后,Py-Spy会开始持续采样目标进程的函数调用栈,采样时间默认是60秒,也可以自己通过--duration参数指定采样时长,比如采样30秒:

py-spy record -o profile.svg --pid 12345 --duration 30

火焰图分析死锁位置

采样完成后,会生成对应的SVG格式火焰图文件,用浏览器打开这个文件即可查看。火焰图的横轴表示采样到的函数调用栈,纵轴表示调用栈的深度,每一个色块代表一个函数,色块的宽度代表该函数的采样命中次数,也就是函数执行耗时的相对占比。

分析死锁问题时,我们可以重点关注以下内容:

  • 寻找宽度特别大且处于调用栈底层的函数,这类函数往往是阻塞的核心逻辑
  • 查看是否有多个线程的调用栈都卡在获取锁的相关逻辑上,比如threading.Lock.acquire相关的调用
  • 检查是否存在循环等待锁的情况,比如线程A持有锁1等待锁2,线程B持有锁2等待锁1

以下是一个模拟死锁的Python代码示例,我们可以用它来验证Py-Spy的分析效果:

import threading
import time

# 定义两个锁
lock1 = threading.Lock()
lock2 = threading.Lock()

def thread_func1():
    # 线程1先获取锁1,再尝试获取锁2
    with lock1:
        print("线程1获取锁1")
        time.sleep(1)
        print("线程1尝试获取锁2")
        with lock2:
            print("线程1获取锁2")

def thread_func2():
    # 线程2先获取锁2,再尝试获取锁1
    with lock2:
        print("线程2获取锁2")
        time.sleep(1)
        print("线程2尝试获取锁1")
        with lock1:
            print("线程2获取锁1")

if __name__ == "__main__":
    t1 = threading.Thread(target=thread_func1)
    t2 = threading.Thread(target=thread_func2)
    t1.start()
    t2.start()
    # 主线程等待子线程执行
    t1.join()
    t2.join()

运行上述代码后,进程会卡住进入死锁状态,此时我们用Py-Spy附加到这个进程生成火焰图,就可以看到两个子线程的调用栈都卡在acquire相关的逻辑上,对应到代码就是两个线程互相等待对方持有的锁,从而快速定位死锁位置。

其他常用Py-Spy命令

除了生成火焰图,Py-Spy还支持实时查看进程的函数调用栈,执行以下命令可以每秒输出一次当前进程的所有线程调用栈:

py-spy top --pid 12345

如果需要查看更详细的调用栈信息,可以使用dump命令直接输出当前所有线程的调用栈:

py-spy dump --pid 12345

注意事项

使用Py-Spy时需要注意以下几点:

  • 附加到进程需要对应的系统权限,在Linux系统中如果提示权限不足,可以加上sudo执行命令
  • Py-Spy目前主要支持CPython解释器,对其他Python实现的支持可能不完善
  • 采样过程对目标进程的性能影响极小,可以放心用于线上环境的排查

PythonPy-Spy火焰图死锁调试修改时间:2026-07-11 03:21:11

免责声明:​ 已尽一切努力确保本网站所含信息的准确性。网站内容多为原创整理与精心编撰,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们处理。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。