Created on 2005-06-30 19:06 by ellisj, last changed 2011-09-11 18:55 by nikratio.
|msg25694 - (view)||Author: Jonathan Ellis (ellisj)||Date: 2005-06-30 19:06|
simple script to reproduce: import sys, threading def log_exception(*args): print 'got exception %s' % (args,) sys.excepthook = log_exception def foo(): a = 1 / 0 threading.Thread(target=foo).start() Note that a normal traceback is printed instead of "got exception."
|msg25695 - (view)||Author: Michael Hudson (mwh)||Date: 2007-06-06 11:11|
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.
|msg25696 - (view)||Author: Jonathan Ellis (ellisj)||Date: 2007-06-15 02:04|
Here is a workaround in the meantime: def install_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. """ import sys run_old = threading.Thread.run def run(*args, **kwargs): try: run_old(*args, **kwargs) except (KeyboardInterrupt, SystemExit): raise except: sys.excepthook(*sys.exc_info()) threading.Thread.run = run
|msg62933 - (view)||Author: Tiago Alves (tiagoaoa)||Date: 2008-02-24 20:40|
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.
|msg91243 - (view)||Author: Ian Beaver (undercoveridiot)||Date: 2009-08-03 21:59|
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: import sys import logging from functools import wraps def myExceptHook(type, value, tb): """ Redirect tracebacks to error log """ import traceback rawreport = traceback.format_exception(type, value, tb) report = '\n'.join(rawreport) log.error(report) sys.excepthook = myExceptHook def use_my_excepthook(view): """ Redirect any unexpected tracebacks """ @wraps(view) def run(*args, **kwargs): try: return view(*args, **kwargs) except: sys.excepthook(*sys.exc_info()) return run Then in your thread subclass: class MyThread(threading.Thread): def __init__(self, socket_conn): threading.Thread.__init__(self) self.my_conn = socket_conn @use_my_excepthook def run(self): """ Do stuff """
|msg91244 - (view)||Author: Ian Beaver (undercoveridiot)||Date: 2009-08-03 22:24|
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. def installThreadExcepthook(): """ Workaround for sys.excepthook thread bug From http://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__ def init(self, *args, **kwargs): init_old(self, *args, **kwargs) run_old = self.run def run_with_except_hook(*args, **kw): try: run_old(*args, **kw) except (KeyboardInterrupt, SystemExit): raise except: sys.excepthook(*sys.exc_info()) self.run = run_with_except_hook threading.Thread.__init__ = init
|2010-08-04 04:44:18||terry.reedy||set||stage: test needed|
versions: + Python 2.7, Python 3.2, - Python 2.6, Python 2.5
|2009-08-03 22:24:03||undercoveridiot||set||messages: + msg91244|
messages: + msg91243
messages: + msg62933
|2007-11-23 09:20:55||christian.heimes||set||versions: + Python 2.6, Python 2.5, - Python 2.4|