1. 程式人生 > >Python3執行時檢視執行緒資訊

Python3執行時檢視執行緒資訊

前一篇文章說了一下在是用Python2的情況下怎樣檢視執行時執行緒資訊,今天查資料的時候發現,原來在Python3中引入了 faulthandler 模組,可以簡化我們很多工作,甚至,如果不需要保持程序繼續執行的情況下可以不用修改我們已有的程式碼。具體 faulthandler 模組的使用,可以參考:

先準備一個小程式,就是週期性的往命令列終端輸出一下時間,如下:

#!/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 環境變數
  2. 使用 python3 -q -X faulthandler 來起用
  3. 程式碼方式來啟用

這裡我們通過設定環境變數 “PYTHONFAULTHANDLER=true” 來啟用,用下面方式執行程式:

$ PYTHONFAULTHANDLER=true ./test.py

然後在另開一個終端執行下面的命令

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

此時我們可以在執行 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)

這裡我們是通過傳送 SIGABRT 訊號來觸發的,其實也可以使用 SIGSEGV, SIGFPE, SIGABRT, SIGBUS 和 SIGILL 訊號來出發。

執行上面的程式,我們發現一個問題,一旦dump threads後,程序就退出了,而如果我們不想讓程序退出,該怎麼辦呢,這就要用到前一篇文章中說提到的複寫訊號處理函數了。

看一下下面的程式碼,我們和前一篇部落格中一樣都是複寫 “SIGQUIT” 訊號處理函式,在接受到 SIGQUIT 訊號後,輸出執行緒資訊到 /tmp 目錄下,然後程式繼續執行。

#!/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)

執行上面的程式,並使用下面的命令來給程序發 SIGQUIT 訊號

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

然後可以在 /tmp 目錄下找到輸出的執行緒日誌,內容如下,同時我們也可以看到程式會繼續執行下去而不會推出。

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>