Python3運(yùn)行時(shí)查看線程信息

前一篇文章說了一下在是用Python2的情況下怎樣查看運(yùn)行時(shí)線程信息,今天查資料的時(shí)候發(fā)現(xiàn),原來在Python3中引入了 faulthandler 模塊,可以簡(jiǎn)化我們很多工作,甚至,如果不需要保持進(jìn)程繼續(xù)運(yùn)行的情況下可以不用修改我們已有的代碼。具體 faulthandler 模塊的使用,可以參考:

faulthandler https://docs.python.org/3/library/faulthandler.html

先準(zhǔn)備一個(gè)小程序,就是周期性的往命令行終端輸出一下時(shí)間,如下:

#!/usr/bin/env python
# -*- coding: utf-8 -*-
import os
import sys
import threading
import traceback
import signal
import tempfile
from datetime import datetime
import time


def test():
    while True:
        print(datetime.now())
        time.sleep(2)


if __name__ == "__main__":
    try:
        threading.Thread(target=test).start()

        while True:
            time.sleep(60)
    except KeyboardInterrupt:
        sys.exit(1)

要啟用 dump thread 的功能,可以通過三種方式來打開:

  1. 使用 PYTHONFAULTHANDLER=true 環(huán)境變量
  2. 使用 python3 -q -X faulthandler 來起用
  3. 代碼方式來啟用

這里我們通過設(shè)置環(huán)境變量 “PYTHONFAULTHANDLER=true” 來啟用,用下面方式運(yùn)行程序:

$ PYTHONFAULTHANDLER=true ./test.py

然后在另開一個(gè)終端運(yùn)行下面的命令

$ kill -SIGABRT `ps -ef | grep test.py | grep -v 'grep' | awk '{print $2}'`

此時(shí)我們可以在運(yùn)行 test.py 的終端中看到如下線程信息:

Fatal Python error: Aborted

Thread 0x00007f8298430700 (most recent call first):
  File "./test3.py", line 16 in test
  File "/usr/lib64/python3.4/threading.py", line 859 in run
  File "/usr/lib64/python3.4/threading.py", line 911 in _bootstrap_inner
  File "/usr/lib64/python3.4/threading.py", line 879 in _bootstrap

Current thread 0x00007f82a2fcf740 (most recent call first):
  File "./test3.py", line 24 in <module>
Aborted (core dumped)

這里我們是通過發(fā)送 SIGABRT 信號(hào)來觸發(fā)的,其實(shí)也可以使用 SIGSEGV, SIGFPE, SIGABRT, SIGBUS 和 SIGILL 信號(hào)來出發(fā)。

運(yùn)行上面的程序,我們發(fā)現(xiàn)一個(gè)問題,一旦dump threads后,進(jìn)程就退出了,而如果我們不想讓進(jìn)程退出,該怎么辦呢,這就要用到前一篇文章中說提到的復(fù)寫信號(hào)處理函數(shù)了。

看一下下面的代碼,我們和前一篇博客中一樣都是復(fù)寫 “SIGQUIT” 信號(hào)處理函數(shù),在接受到 SIGQUIT 信號(hào)后,輸出線程信息到 /tmp 目錄下,然后程序繼續(xù)運(yùn)行。

#!/usr/bin/env /usr/bin/python3.4
# -*- coding: utf-8 -*-
import os
import sys
import threading
import traceback
import signal
import tempfile
from datetime import datetime
import time
import faulthandler


def test():
    while True:
        print(datetime.now())
        time.sleep(2)


def signal_handler(signum, frame):
    try:
        file = os.path.join(tempfile.gettempdir(), datetime.now().strftime('%Y%m%d%H%M%S') + ".log")
        with open(file, 'w+') as f:
            faulthandler.dump_traceback(file=f, all_threads=True)
    except BaseException as e:
        print(e)


if __name__ == "__main__":
    try:
        signal.signal(signal.SIGQUIT, signal_handler)

        threading.Thread(target=test).start()

        while True:
            time.sleep(60)
    except KeyboardInterrupt:
        sys.exit(1)

運(yùn)行上面的程序,并使用下面的命令來給進(jìn)程發(fā) SIGQUIT 信號(hào)

$ kill -SIGQUIT `ps -ef | grep test.py | grep -v 'grep' | awk '{print $2}'`

然后可以在 /tmp 目錄下找到輸出的線程日志,內(nèi)容如下,同時(shí)我們也可以看到程序會(huì)繼續(xù)執(zhí)行下去而不會(huì)推出。

Thread 0x00007f13d75d2700 (most recent call first):
  File "./test3.py", line 17 in test
  File "/usr/lib64/python3.4/threading.py", line 859 in run
  File "/usr/lib64/python3.4/threading.py", line 911 in _bootstrap_inner
  File "/usr/lib64/python3.4/threading.py", line 879 in _bootstrap

Current thread 0x00007f13e2171740 (most recent call first):
  File "./test3.py", line 24 in signal_handler
  File "./test3.py", line 36 in <module>

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

推薦閱讀更多精彩內(nèi)容