You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Add threading.excepthook() to handle uncaught exceptions raised by Thread.run() #42148
I've just run into this, and it's very annoying. The stupid part is that threads started with the thread module don't have this problem, it's just a problem with threading.Thread()s trying to be too clever.
I would vote for deleting all the code to do with exception printing in threading.py and letting the C machinery take care of it.
ellisj commented on Jun 15, 2007
ellisjmannequin
MannequinAuthor
More actions
Here is a workaround in the meantime:
definstall_thread_excepthook():
""" Workaround for sys.excepthook thread bug (https://sourceforge.net/tracker/?func=detail&atid=105470&aid=1230540&group_id=5470). Call once from __main__ before creating any threads. If using psyco, call psycho.cannotcompile(threading.Thread.run) since this replaces a new-style class method. """importsysrun_old=threading.Thread.rundefrun(*args, **kwargs):
try:
run_old(*args, **kwargs)
except (KeyboardInterrupt, SystemExit):
raiseexcept:
sys.excepthook(*sys.exc_info())
threading.Thread.run=run
tiagoaoa commented on Feb 24, 2008
tiagoaoamannequin
Mannequin
More actions
I don't see it as a problem or as the threading module trying to be
"clever". It clearly was a design choice to make the module have its own
exception treatment in order to make it clear in which thread the
exception occurred.
IMHO the decision here should be to implement per thread excepthook's.
undercoveridiot commented on Aug 3, 2009
undercoveridiotmannequin
Mannequin
More actions
I found that the workaround suggested doesn't work when you have a
subclass of threading.Thread and you want to catch everything in the
module that contains the class to a common log.
Say you have a module with a socket server that spawns a thread on
accept and you want to log anything that tracebacks in the module. This
seems to work:
classMyThread(threading.Thread):
def__init__(self, socket_conn):
threading.Thread.__init__(self)
self.my_conn=socket_conn@use_my_excepthookdefrun(self):
""" Do stuff """
undercoveridiot commented on Aug 3, 2009
undercoveridiotmannequin
Mannequin
More actions
Instead of using decorators, this is a slightly simpler modification to
the proposed workaround that allows for any subclassed run method to
also be caught.
definstallThreadExcepthook():
""" Workaround for sys.excepthook thread bug Fromhttp://spyced.blogspot.com/2007/06/workaround-for-sysexcepthook-bug.html(https://sourceforge.net/tracker/?func=detail&atid=105470&aid=1230540&group_id=5470). Call once from __main__ before creating any threads. If using psyco, call psyco.cannotcompile(threading.Thread.run) since this replaces a new-style class method. """init_old=threading.Thread.__init__definit(self, *args, **kwargs):
init_old(self, *args, **kwargs)
run_old=self.rundefrun_with_except_hook(*args, **kw):
try:
run_old(*args, **kw)
except (KeyboardInterrupt, SystemExit):
raiseexcept:
sys.excepthook(*sys.exc_info())
self.run=run_with_except_hookthreading.Thread.__init__=init
AraHaan commented on Aug 5, 2016
AraHaanmannequin
Mannequin
More actions
I too agree that I hate the thread exceptions being printed in the console I would suggest python was to error log it all to a file instead (so it does not spam up the console). I get it a lot with websocket / opus errors and it is annoying because it does not cleanup ffmpeg for me.
AraHaan commented on Aug 5, 2016
AraHaanmannequin
Mannequin
More actions
personally these exceptions in console can be annoying to me as I hate seeing them.
Exception in thread Thread-11:
Traceback (most recent call last):
File "threading.py", line 914, in _bootstrap_inner
File "E:\Users\Elsword\Desktop\DecoraterBot\Async\test\resources\Dependencies\discord\voice_client.py", line 150, in runsuper().run()
File "E:\Users\Elsword\Desktop\DecoraterBot\Async\test\resources\Dependencies\discord\voice_client.py", line 108, in runself.player(data)
File "E:\Users\Elsword\Desktop\DecoraterBot\Async\test\resources\Dependencies\discord\voice_client.py", line 669, in play_audio
sent =self.socket.sendto(packet, (self.endpoint_ip, self.voice_port))
OSError: [WinError 10055] An operation on a socket could not be performed because the system lacked sufficient buffer space or because a queue was full
Exception in thread Thread-21:
Traceback (most recent call last):
File "threading.py", line 914, in _bootstrap_inner
File "E:\Users\Elsword\Desktop\DecoraterBot\Async\test\resources\Dependencies\discord\voice_client.py", line 150, in runsuper().run()
File "E:\Users\Elsword\Desktop\DecoraterBot\Async\test\resources\Dependencies\discord\voice_client.py", line 108, in runself.player(data)
File "E:\Users\Elsword\Desktop\DecoraterBot\Async\test\resources\Dependencies\discord\voice_client.py", line 669, in play_audio
sent =self.socket.sendto(packet, (self.endpoint_ip, self.voice_port))
OSError: [WinError 10038] An operation was attempted on something that is not a socket
AraHaan commented on Aug 5, 2016
AraHaanmannequin
Mannequin
More actions
Ok, so I just found out you can bypass thread exceptions by wraping the line that actually runs the threads in a try/except block and then using the logging module to log it to a file instead of the console.
CyberJacob commented on Feb 24, 2017
CyberJacobmannequin
Mannequin
More actions
Does this affect threads started with the multiprocessing library as well?
CyberJacob commented on Feb 24, 2017
CyberJacobmannequin
Mannequin
More actions
Just confirmed, this does affect multiprocessing. script to reproduce:
Apparently the traceback module has been used from the start (since changset 7f5013a) to print the exception and not sys.excepthook. I presume this is an oversight, as I don't see any reason to prefer traceback here. Tim, any insight?
I don't see the relationship between the API (signature) and the ability to set a per-thread hook.
I'm not convinced that a per-thread hook is needed.
Indeed, if you write your own Thread class, you can add a try...except
in the Thread.run() method. You don't need a dedicated
Thread.excepthook() method.
The only way a per-thread hook could be useful is if you could set it
*outside* of the Thread class (so not as a method), so that one can e.g.
catch / report exceptions raised in threads launches by third-party
libraries.
Indeed, if you write your own Thread class, you can add a try...except
in the Thread.run() method. You don't need a dedicated
Thread.excepthook() method.
Exactly. You can already do you best in your run() method to handle exceptions.
threading.excepthook is only there is everything else already failed.
FYI in my implementation, if threading.excepthook raises a new exception, it's also handled... by sys.excepthook this time ;-)
The only way a per-thread hook could be useful is if you could set it
*outside* of the Thread class (so not as a method), so that one can e.g.
catch / report exceptions raised in threads launches by third-party
libraries.
I discuss threading excepthook with Pablo and he asked me if it would be possible to have a different behavior depending if the thread is spawn by my application or by "third party code". Using threading.excepthook, you can mark your threads that you spawn directly using a specific name, a special attribute, or you may even track them in a list (maybe using weak references).
If sys.excepthook is used to handle threading exceptions, you call threading.current_thread(), but then we come back to the issue to "dying" Python: exception which occurs late in Python finalization, when most modules are already cleared and import no longer works.
In any case, I think the namedtuple / structseq solution is elegant, because we can add additional information later
I used the same design for the new sys.unraisablehook in bpo-36829 and I'm already working on adding a new 'err_msg' field to the argument passed to this took: PR 13488 :-)
I was trapped in the past when I had to modify warnings "hooks" (warnings.showwarning and warnings.formatwarning) when I had to add a new 'source' parameter. I had to write wrappers which are fragile, to keep the backward compatibility.
(the user must only be careful not to use tuple unpacking)
threading.excepthook doesn't mention the compatibility with tuple on purpose. It only documents attributes with their names.
If we want to support low-level threads created by start_new_thread() we should call excepthook() from t_bootstrap instead of Thread._bootstrap_inner. Otherwise implementing excepthook() as a Thread method would be more convenient.
changed the title [-]sys.excepthook doesn't work in threads[/-][+]Add threading.excepthook() to handle uncaught exceptions raised by Thread.run()[/+]on May 28, 2019
changed the title [-]sys.excepthook doesn't work in threads[/-][+]Add threading.excepthook() to handle uncaught exceptions raised by Thread.run()[/+]on May 28, 2019
If we want to support low-level threads created by start_new_thread() we should call excepthook() from t_bootstrap instead of Thread._bootstrap_inner. Otherwise implementing excepthook() as a Thread method would be more convenient.
I created bpo-37076: "_thread.start_new_thread(): call sys.unraisablehook() to handle uncaught exceptions".
Activity
ellisj commentedon Jun 30, 2005
simple script to reproduce:
Note that a normal traceback is printed instead of "got
exception."
mwhudson commentedon Jun 6, 2007
I've just run into this, and it's very annoying. The stupid part is that threads started with the thread module don't have this problem, it's just a problem with threading.Thread()s trying to be too clever.
I would vote for deleting all the code to do with exception printing in threading.py and letting the C machinery take care of it.
ellisj commentedon Jun 15, 2007
Here is a workaround in the meantime:
tiagoaoa commentedon Feb 24, 2008
I don't see it as a problem or as the threading module trying to be
"clever". It clearly was a design choice to make the module have its own
exception treatment in order to make it clear in which thread the
exception occurred.
IMHO the decision here should be to implement per thread excepthook's.
undercoveridiot commentedon Aug 3, 2009
I found that the workaround suggested doesn't work when you have a
subclass of threading.Thread and you want to catch everything in the
module that contains the class to a common log.
Say you have a module with a socket server that spawns a thread on
accept and you want to log anything that tracebacks in the module. This
seems to work:
Then in your thread subclass:
undercoveridiot commentedon Aug 3, 2009
Instead of using decorators, this is a slightly simpler modification to
the proposed workaround that allows for any subclassed run method to
also be caught.
AraHaan commentedon Aug 5, 2016
I too agree that I hate the thread exceptions being printed in the console I would suggest python was to error log it all to a file instead (so it does not spam up the console). I get it a lot with websocket / opus errors and it is annoying because it does not cleanup ffmpeg for me.
AraHaan commentedon Aug 5, 2016
personally these exceptions in console can be annoying to me as I hate seeing them.
AraHaan commentedon Aug 5, 2016
Ok, so I just found out you can bypass thread exceptions by wraping the line that actually runs the threads in a try/except block and then using the logging module to log it to a file instead of the console.
CyberJacob commentedon Feb 24, 2017
Does this affect threads started with the multiprocessing library as well?
CyberJacob commentedon Feb 24, 2017
Just confirmed, this does affect multiprocessing. script to reproduce:
multiprocessing.Process(target=foo).start()
again, just a normal traceback instead of "got exception"
pitrou commentedon Jun 28, 2017
Apparently the
tracebackmodule has been used from the start (since changset 7f5013a) to print the exception and not sys.excepthook. I presume this is an oversight, as I don't see any reason to prefertracebackhere. Tim, any insight?29 remaining items
pitrou commentedon May 25, 2019
Le 25/05/2019 à 23:09, STINNER Victor a écrit :
Indeed, if you write your own Thread class, you can add a try...except
in the Thread.run() method. You don't need a dedicated
Thread.excepthook() method.
The only way a per-thread hook could be useful is if you could set it
*outside* of the Thread class (so not as a method), so that one can e.g.
catch / report exceptions raised in threads launches by third-party
libraries.
vstinner commentedon May 25, 2019
Exactly. You can already do you best in your run() method to handle exceptions.
threading.excepthook is only there is everything else already failed.
FYI in my implementation, if threading.excepthook raises a new exception, it's also handled... by sys.excepthook this time ;-)
I discuss threading excepthook with Pablo and he asked me if it would be possible to have a different behavior depending if the thread is spawn by my application or by "third party code". Using threading.excepthook, you can mark your threads that you spawn directly using a specific name, a special attribute, or you may even track them in a list (maybe using weak references).
If sys.excepthook is used to handle threading exceptions, you call threading.current_thread(), but then we come back to the issue to "dying" Python: exception which occurs late in Python finalization, when most modules are already cleared and import no longer works.
vstinner commentedon May 25, 2019
Antoine Pitrou:
I modified my PR to use the threading identitifer (threading.get_ident()) as the thread name if args.thread is None.
vstinner commentedon May 25, 2019
I used the same design for the new sys.unraisablehook in bpo-36829 and I'm already working on adding a new 'err_msg' field to the argument passed to this took: PR 13488 :-)
I was trapped in the past when I had to modify warnings "hooks" (warnings.showwarning and warnings.formatwarning) when I had to add a new 'source' parameter. I had to write wrappers which are fragile, to keep the backward compatibility.
threading.excepthook doesn't mention the compatibility with tuple on purpose. It only documents attributes with their names.
vstinner commentedon May 27, 2019
New changeset cd590a7 by Victor Stinner in branch 'master':
bpo-1230540: Add threading.excepthook() (GH-13515)
cd590a7
vstinner commentedon May 27, 2019
It took 14 years, but this issue is now fixed ;-) I close it.
Python 3.8 beta 1 will be released in a few days with threading.excepthook(): please test it to ensure that it works as you expected.
As a follow-up, I created bpo-37069: "regrtest: log unraisable exceptions and uncaught thread exceptions".
serhiy-storchaka commentedon May 28, 2019
If we want to support low-level threads created by start_new_thread() we should call excepthook() from t_bootstrap instead of Thread._bootstrap_inner. Otherwise implementing excepthook() as a Thread method would be more convenient.
[-]sys.excepthook doesn't work in threads[/-][+]Add threading.excepthook() to handle uncaught exceptions raised by Thread.run()[/+][-]sys.excepthook doesn't work in threads[/-][+]Add threading.excepthook() to handle uncaught exceptions raised by Thread.run()[/+]vstinner commentedon May 28, 2019
I created bpo-37076: "_thread.start_new_thread(): call sys.unraisablehook() to handle uncaught exceptions".
Make logging of exception which occurred on non main thread less verb…
Make logging of exception which occurred on non main thread less verb…