Thread Dumps – auch für Python

Thread Dumps sind Momentaufnahmen des Aufruf-Stacks für jeden Thread einer laufenden multi-thread Anwendung. Dies ist in vielen Situationen zur Analyse hilfreich. Diese gestaltet sich gerade bei multi-thread Anwendung meist komplizierter.

Für Java gibt es das Programm jstack (u.a. mit jps im JRE enthalten) um Thread Dumps zu erzeugen.

Unter Python kann ein ähnliches Verhalten (getestet unter Linux) mit einem kleinen Umweg über einen Signal-Handler erreicht werden:

...
import faulthandler 
import signal
import os
...

def handler(signum, frame):
  file ='/tmp/threads'
  print('Writing thread dump to ', file)
  with open(file, 'w') as f:
    faulthandler.dump_traceback(file=f, all_threads=True)

...
if __name__ == '__main__':
  with open('/tmp/pid', 'w') as f:
    f.write(str(os.getpid()))
  signal.signal(signal.SIGUSR1, handler)
  ...

Nach dem Starten des Programms kann man über die PID aus /tmp/pid einen Thread Dump erzeugen:

kill -USR1 `cat/tmp/pid`

Dieser sieht exemplarisch so aus (extra in kleinerer Schriftart um die Zeilen ohne Umbrüche zu erhalten):

Thread 0xb3ccb460 (most recent call first):
 File "/home/jlusiardi/.local/lib/python3.4/site-packages/zeroconf.py", line 1102 in run
 File "/usr/lib/python3.4/threading.py", line 920 in _bootstrap_inner
 File "/usr/lib/python3.4/threading.py", line 888 in _bootstrap

Thread 0xb44ff460 (most recent call first):
 File "/usr/lib/python3.4/socketserver.py", line 154 in _eintr_retry
 File "/usr/lib/python3.4/socketserver.py", line 236 in serve_forever
 File "/home/jlusiardi/sources/smarthome/homekit_link/__init__.py", line 142 in run
 File "/usr/lib/python3.4/threading.py", line 920 in _bootstrap_inner
 File "/usr/lib/python3.4/threading.py", line 888 in _bootstrap

Thread 0xb4cff460 (most recent call first):
 File "/home/jlusiardi/sources/smarthome/influxdb/__init__.py", line 109 in run
 File "/usr/lib/python3.4/threading.py", line 920 in _bootstrap_inner
 File "/usr/lib/python3.4/threading.py", line 888 in _bootstrap

Thread 0xb6025460 (most recent call first):
 File "/usr/lib/python3.4/socketserver.py", line 154 in _eintr_retry
 File "/usr/lib/python3.4/socketserver.py", line 236 in serve_forever
 File "/home/jlusiardi/sources/smarthome/homematic/callback.py", line 42 in run
 File "/usr/lib/python3.4/threading.py", line 920 in _bootstrap_inner
 File "/usr/lib/python3.4/threading.py", line 888 in _bootstrap

Current thread 0xb6fb6300 (most recent call first):
 File "./main.py", line 19 in handler
 File "/usr/lib/python3.4/cmd.py", line 126 in cmdloop
 File "/home/jlusiardi/sources/smarthome/cli/__init__.py", line 32 in cmdloop
 File "./main.py", line 50 in <module>

Auch hier bieten sich verbesserte Analysemöglichkeiten analog zu Java.