faulthandler and sys hook in python

faulthandler module : Dump the Python traceback

General

Content: functions to dump Python tracebacks explicitly, on a fault, after a timeout, or on a user signal.
Signals/Faults handled: SIGSEGV, SIGFPE, SIGABRT, SIGBUS, SIGILL
Warning:
The fault handler is called on catastrophic cases and therefore can only use signal-safe functions (e.g. it cannot allocate memory on the heap). Because of this limitation traceback dumping is minimal compared to normal Python tracebacks.
Not exhaustive :
– only ASCII
– limited to 500 characters
– only the filename, the function name and the line number are displayed. (no source code)

How to enable it?
We have two ways:
– Call faulthandler.enable().
– setting the PYTHONFAULTHANDLER environment variable or by using the -X faulthandler command line option.

Where the faults are traced?
By default, the Python traceback is written to sys.stderr.
A log file can alternatively be passed to faulthandler.enable().

Dumping the traceback

Dump the tracebacks of all threads into file.
If all_threads is False, dump only the current thread.
faulthandler.dump_traceback(file=sys.stderr, all_threads=True)

Dumping the tracebacks after a timeout

Dump the tracebacks of all threads, after a timeout of timeout seconds, or every timeout seconds if repeat is True.
If exit is True, call _exit() with status=1 after dumping the tracebacks:
faulthandler.dump_traceback_later(timeout, repeat=False, file=sys.stderr, exit=False)

Cancel the last call to dump_traceback_later():
faulthandler.cancel_dump_traceback_later()

Dumping the traceback on a user signal

Works only on linux.

faulthandler Examples

faulthandler with signal

import faulthandler
import signal
 
 
def a():
    # We raise an illegal instruction signal.
    signal.raise_signal(signal.SIGILL)
 
 
faulthandler.enable()
 
a()

Output:

Fatal Python error: Illegal instruction
 
Current thread 0x00005154 (most recent call first):
  File "C:\programmation\workspace-python\python_blog_examples\faulthandler_and_sys_hook\faulthandler_with_signal.py", line 7 in a
  File "C:\programmation\workspace-python\python_blog_examples\faulthandler_and_sys_hook\faulthandler_with_signal.py", line 12 in <module>

print threads dump with faulthandler.dump_traceback()

    import faulthandler
    import sys
    from threading import Thread
    from time import sleep
 
 
    def a():
        i: int = 0
        while True:
            i += 1
            sleep(0.25)
 
 
    def b():
        sleep(5)
 
 
    faulthandler.enable()
 
    Thread(daemon=True, name='a', target=lambda: a()).start()
    Thread(daemon=True, name='b', target=lambda: b()).start()
    faulthandler.dump_traceback()
    sys.exit()

Output:

Thread 0x00002224 (most recent call first):
  File "C:\programmation\workspace-python\python_blog_examples\faulthandler_and_sys_hook\faulthandler_dump_traceback_of_all_threads.py", line 15 in b
  File "C:\programmation\workspace-python\python_blog_examples\faulthandler_and_sys_hook\faulthandler_dump_traceback_of_all_threads.py", line 21 in <lambda>
  File "C:\Users\david\AppData\Local\Programs\Python\Python310\lib\threading.py", line 953 in run
  File "C:\Users\david\AppData\Local\Programs\Python\Python310\lib\threading.py", line 1016 in _bootstrap_inner
  File "C:\Users\david\AppData\Local\Programs\Python\Python310\lib\threading.py", line 973 in _bootstrap
 
Thread 0x00003a9c (most recent call first):
  File "C:\programmation\workspace-python\python_blog_examples\faulthandler_and_sys_hook\faulthandler_dump_traceback_of_all_threads.py", line 11 in a
  File "C:\programmation\workspace-python\python_blog_examples\faulthandler_and_sys_hook\faulthandler_dump_traceback_of_all_threads.py", line 20 in <lambda>
  File "C:\Users\david\AppData\Local\Programs\Python\Python310\lib\threading.py", line 953 in run
  File "C:\Users\david\AppData\Local\Programs\Python\Python310\lib\threading.py", line 1016 in _bootstrap_inner
  File "C:\Users\david\AppData\Local\Programs\Python\Python310\lib\threading.py", line 973 in _bootstrap
 
Current thread 0x000049d4 (most recent call first):
  File "C:\programmation\workspace-python\python_blog_examples\faulthandler_and_sys_hook\faulthandler_dump_traceback_of_all_threads.py", line 22 in <module>

repeat print threads dump with dump_traceback_later()

import faulthandler
from threading import Thread
from time import sleep
 
 
def a():
    i: int = 0
    while True:
        i += 1
        sleep(0.25)
 
 
def b():
    sleep(5)
 
 
faulthandler.enable()
 
thread_a = Thread(daemon=True, name='a', target=lambda: a())
thread_a.start()
thread_b = Thread(daemon=True, name='b', target=lambda: b())
thread_b.start()
faulthandler.dump_traceback_later(repeat=True, timeout=2)
thread_a.join()
thread_b.join()

Output:

	Timeout (0:00:02)!
Thread 0x00004870 (most recent call first):
  File "C:\programmation\workspace-python\python_blog_examples\faulthandler_and_sys_hook\faulthandler_dump_traceback_later.py", line 14 in b
  File "C:\programmation\workspace-python\python_blog_examples\faulthandler_and_sys_hook\faulthandler_dump_traceback_later.py", line 21 in <lambda>
  File "C:\Users\david\AppData\Local\Programs\Python\Python310\lib\threading.py", line 953 in run
  File "C:\Users\david\AppData\Local\Programs\Python\Python310\lib\threading.py", line 1016 in _bootstrap_inner
  File "C:\Users\david\AppData\Local\Programs\Python\Python310\lib\threading.py", line 973 in _bootstrap
 
Thread 0x00002c64 (most recent call first):
  File "C:\programmation\workspace-python\python_blog_examples\faulthandler_and_sys_hook\faulthandler_dump_traceback_later.py", line 10 in a
  File "C:\programmation\workspace-python\python_blog_examples\faulthandler_and_sys_hook\faulthandler_dump_traceback_later.py", line 19 in <lambda>
  File "C:\Users\david\AppData\Local\Programs\Python\Python310\lib\threading.py", line 953 in run
  File "C:\Users\david\AppData\Local\Programs\Python\Python310\lib\threading.py", line 1016 in _bootstrap_inner
  File "C:\Users\david\AppData\Local\Programs\Python\Python310\lib\threading.py", line 973 in _bootstrap
 
Thread 0x000053d8 (most recent call first):
  File "C:\Users\david\AppData\Local\Programs\Python\Python310\lib\threading.py", line 1116 in _wait_for_tstate_lock
  File "C:\Users\david\AppData\Local\Programs\Python\Python310\lib\threading.py", line 1096 in join
  File "C:\programmation\workspace-python\python_blog_examples\faulthandler_and_sys_hook\faulthandler_dump_traceback_later.py", line 24 in <module>
Timeout (0:00:02)!
Thread 0x00004870 (most recent call first):
  File "C:\programmation\workspace-python\python_blog_examples\faulthandler_and_sys_hook\faulthandler_dump_traceback_later.py", line 14 in b
  File "C:\programmation\workspace-python\python_blog_examples\faulthandler_and_sys_hook\faulthandler_dump_traceback_later.py", line 21 in <lambda>
  File "C:\Users\david\AppData\Local\Programs\Python\Python310\lib\threading.py", line 953 in run
  File "C:\Users\david\AppData\Local\Programs\Python\Python310\lib\threading.py", line 1016 in _bootstrap_inner
  File "C:\Users\david\AppData\Local\Programs\Python\Python310\lib\threading.py", line 973 in _bootstrap
 
Thread 0x00002c64 (most recent call first):
  File "C:\programmation\workspace-python\python_blog_examples\faulthandler_and_sys_hook\faulthandler_dump_traceback_later.py", line 10 in a
  File "C:\programmation\workspace-python\python_blog_examples\faulthandler_and_sys_hook\faulthandler_dump_traceback_later.py", line 19 in <lambda>
  File "C:\Users\david\AppData\Local\Programs\Python\Python310\lib\threading.py", line 953 in run
  File "C:\Users\david\AppData\Local\Programs\Python\Python310\lib\threading.py", line 1016 in _bootstrap_inner
  File "C:\Users\david\AppData\Local\Programs\Python\Python310\lib\threading.py", line 973 in _bootstrap
 
Thread 0x000053d8 (most recent call first):
  File "C:\Users\david\AppData\Local\Programs\Python\Python310\lib\threading.py", line 1116 in _wait_for_tstate_lock
  File "C:\Users\david\AppData\Local\Programs\Python\Python310\lib\threading.py", line 1096 in join
  File "C:\programmation\workspace-python\python_blog_examples\faulthandler_and_sys_hook\faulthandler_dump_traceback_later.py", line 24 in <module>
Timeout (0:00:02)!
Thread 0x00002c64 (most recent call first):
  File "C:\programmation\workspace-python\python_blog_examples\faulthandler_and_sys_hook\faulthandler_dump_traceback_later.py", line 10 in a......

Sys hooks

sys.excepthook(type, value, traceback)

When an exception is raised and uncaught, before the program exits the interpreter calls sys.excepthook with three arguments, the exception class, exception instance, and a traceback object.
By default, the function prints out a given traceback and exception to sys.stderr.
We can customize this behavior by assigning another three-argument function to sys.excepthook.

Sys hooks Examples

excepthook example with standard out

import sys
import traceback
from types import TracebackType
 
 
def handle_exception(exc_type, exc_value, exc_traceback: TracebackType):
    if issubclass(exc_type, KeyboardInterrupt):
        sys.__excepthook__(exc_type, exc_value, exc_traceback)
        return
 
    print('Uncaught exception:')
    print('Type:', exc_type)
    print('Value:', exc_value)
    # We can use the first or the second method. The result is almost the same.
    # traceback.print_tb(exc_traceback)
    traceback.print_exception(etype=None, value=exc_value, tb=exc_traceback)
 
 
def main():
    invalid = 'a'[1]
 
 
if __name__ == '__main__':
    main()

Output:

Traceback (most recent call last):
  File "C:\programmation\workspace-python\python_blog_examples\faulthandler_and_sys_hook\excepthook_example_with_standard_out.py", line 24, in <module>
    main()
  File "C:\programmation\workspace-python\python_blog_examples\faulthandler_and_sys_hook\excepthook_example_with_standard_out.py", line 20, in main
    invalid = 'a'[1]
IndexError: string index out of range

excepthook example with logging

import logging
import sys
 
logger: logging.Logger
 
 
def handle_exception(exc_type, exc_value, exc_traceback):
    if issubclass(exc_type, KeyboardInterrupt):
        sys.__excepthook__(exc_type, exc_value, exc_traceback)
        return
    logger.error(f"Uncaught exception : {exc_type}",
                 exc_info=(exc_type, exc_value, exc_traceback))
 
 
sys.excepthook = handle_exception
 
 
def main():
    global logger
    logging.basicConfig(level=logging.INFO, format=
    '%(asctime)-15s - %(threadName)s - %(levelname)s : %(name)s.%(funcName)s  %(message)s')
    logger = logging.getLogger('excepthook_example_with_logging')
    invalid = 'a'[1]
 
 
if __name__ == '__main__':
    main()

Output:

2023-04-14 13:54:42,266 - MainThread - ERROR : excepthook_example_with_logging.handle_exception  Uncaught exception : <class 'IndexError'>
Traceback (most recent call last):
  File "C:\programmation\workspace-python\python_blog_examples\faulthandler_and_sys_hook\excepthook_example_with_logging.py", line 27, in <module>
    main()
  File "C:\programmation\workspace-python\python_blog_examples\faulthandler_and_sys_hook\excepthook_example_with_logging.py", line 23, in main
    invalid = 'a'[1]
IndexError: string index out of range
Ce contenu a été publié dans Non classé. Vous pouvez le mettre en favoris avec ce permalien.

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *