打印python线程stack分析当前上下文

前言:

      Python技术群里( 478476595 )经常有朋友问我,如何分析python服务里各种诡异的你问题,比如线程不工作、死锁、hang住没动静、不输出日志、不处理任务 等等问题。 我想大家应该在工作中也经常遇到过该问题。我在这里告诉大家如何快速的分析该问题。

      该文章后续仍在不断的更新修改中, 请移步到原文地址 http://xiaorui.cc/?p=5219

      通常,我们可以打印python的函数调用栈stack来分析问题。 好的,我们来跑一个下面的例子,当我们触发信号USR1的时候,该程序会向终端输出python thread stack过程信息。 其实关键方法在于  traceback.print_stack(sys._current_frames()[thread.ident]) , sys_current_frames是可以拿到线程的调用栈信息。

下图是打印的结果:


既然有了函数调用栈信息,那么你可以分析各种问题,比如上面说的死锁问题,队列不消费的问题。 比如队列为什么不消费,那么你可以打印消费者的线程来分析过程。

像有些语言是可以通过系统的pstack来打印调用栈的,比如C语言。但pstack不适用于python、java、golang的。 拿python来说,我们通过pstack打印出来的调用栈信息都是python运行时的代码。这些信息虽然确实是pthread线程里真实的函数调用栈区,但对于我们来说,其实并不关心这么底层的stack, 而是要看python抽象的frame stack。当然通过pstack是可以看到一些基本信息的,比如启动线程,sleep,入栈出栈的动作信息。


上面说的是多线程打印stack,  多进程的道理是一样的,各自打印罢了。  但如果你是多协程模式,就不能用上面方法了。 比如 gevnet需要用gc.get_objects获取所有对象,然后过滤gr_frame获取gevnet相关的调用栈对象。

要分析asyncio,那么需要用asyncio.Task.all_tasks来获取所有的协程调用栈对象。

总结:

     不限于语言,任务框架都可以使用该方法来解决问题,大同小异。 


END.


对Golang感兴趣的朋友可以加群: 278517979 !!!
另外如果大家觉得文章对你有些作用! 如果想赏钱,可以用微信扫描下面的二维码, 感谢!
另外再次标注博客原地址  xiaorui.cc