STINNER Victor <vstin...@redhat.com> added the comment:

I wrote PR 13515 which adds threading.excepthook(). I chose to call 
threading.excepthook() even when run() raises SystemExit. In this case, 
threading.excepthook() simply does nothing. The idea is to really give the full 
control when threading.excepthook() is overriden. For example, log a warning 
when run() raises SystemExit. By the way, is it really a good idea to call 
sys.exit() from a thread? It sounds like a bug that should be reported, and not 
silently ignored, no?

Differences between sys.excepthook() and threading.excepthook():

* API: sys.excepthook(exctype, value, traceback, /) vs 
threading.excepthook(exc_type, exc_value, exc_tb, thread, /) -- addition thread 
parameter to display the name of the thread which raises an exception

* For SystemExit corner case, sys.excepthook() displays the exception, whereas 
threading.excepthook() silently ignores it

* When sys.stderr is None, sys.excepthook() does nothing, whereas 
threading.excepthook() tries harder: use its own copy of sys.stderr (saved when 
the thread has been created) from thread._stderr.

Thread._stderr was added by bpo-754449:

commit cc4e935ea593cede10cb1316e3faeabd708abca7
Author: Brett Cannon <bcan...@gmail.com>
Date:   Sat Jul 3 03:52:35 2004 +0000

    threading.Thread objects will now print a traceback for an exception raised
    during interpreter shutdown instead of masking it with another traceback 
about
    accessing a NoneType when trying to print the exception out in the first 
place.
    
    Closes bug #754449 (using patch #954922).

Note: When sys.stderr is None, threading.excepthook() avoids the traceback 
module and renders the exception itself. Maybe threading.excepthook() should be 
reimplemented in C to make it even more reliable and more correct, especially 
during Python shutdown. Only daemon threads are impacted: Python finalization 
(Py_Finalize() C function) starts by calling threading._shutdown() which joins 
all non-daemon threads.


IMHO the threading.Thread semantics is too different than sys.excepthook() to 
reuse sys.excepthook() to handle threading.Thread.run() exception.

Another explanation is that sadly sys.excepthook() API uses exactly 3 
positional-only arguments, and so the API cannot be easily extended to get a 
thread argument. When I designed sys.unraisablehook(), I chose to pass only one 
argument which has attributes, to prevent this issue.

I'm not comfortable to attempt to modify sys.excepthook() to make it behave 
differently if it's called from the main thread or from a different thread. It 
would have to call threading.current_thread().name to get the name of the 
current thread.


Let's say that in Python 3.8 threading.Thread now calls sys.execpthook() to 
handle uncaught run() exception. All applications which override 
sys.excepthook() on purpose will behave differently: start to log exceptions 
from threads. But existing code is unlikely to be prepared to implement black 
magic to check if we are a "thread" or the main thread, to decide if we should 
display a thread name, and also the "black magic" to get the current thread 
name.


One of my concern of reusing sys.excepthook to display threading exceptions is 
that adding more code to handle threads is a risk of raising a new exception 
while logging a threading exception :-(

IMHO threading.excepthook() is safer since it already has access to the thread.

----------

_______________________________________
Python tracker <rep...@bugs.python.org>
<https://bugs.python.org/issue1230540>
_______________________________________
_______________________________________________
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com

Reply via email to