Python – Printing Daemonic Thread Exceptions in Python

multithreadingpython

Python does not print traceback messages from exceptions raised in daemon threads.

For example, this code creates a daemonic thread and raises an exception in the new thread:

def error_raiser():
    raise Exception

import threading
thread = threading.Thread(target=error_raiser)
thread.daemon = True
thread.start()

but does not print a traceback. (It gives no output).

However, if the thread is not set as a daemon thread, Python will print the traceback. Here is the same code with one line commented out:

def error_raiser():
    raise Exception

import threading
thread = threading.Thread(target=error_raiser)
# thread.daemon = True
thread.start()

and the output:

Exception in Thread-1:
Traceback (most recent call last):
  File "C:\Python26\lib\threading.py", line 525, in __bootstrap_inner
    self.run()
  File "C:\Python26\lib\threading.py", line 477, in run
    self.__target(*self.__args, **self.__kwargs)
  File "test.py", line 2, in error_raiser
    raise Exception
Exception

Executing this code in both Python 2.6.2 and Python 3.0.1 and gives the same results. Interestingly, however, if I execute the code by importing it in the IPython shell, the exception is displayed whether the thread is daemonic or not.

According to the documentation, the only significance of the 'daemon' flag is that "the entire Python program exits when only daemon threads are left." This would make me believe that not printing a traceback after an exception is a bug in Python, unless I missed something in the documentation.

Is this a bug, or did I miss something in the documentation and this behavior is intentional? If it is intentional, how can I force Python to print the traceback in daemon threads without using IPython?

Best Answer

According to Wikipedia, by definition a daemon should detach itself from the controlling tty, so I think it's correct that no exception is shown (and after all, a daemon should keep working even if you close the shell that launched it)..
See here.

As for how to print the traceback, I think that a simple try/except_then_log_to_file would do the trick :)