diff options
author | Antoine Pitrou <solipsis@pitrou.net> | 2015-01-17 19:02:14 (GMT) |
---|---|---|
committer | Antoine Pitrou <solipsis@pitrou.net> | 2015-01-17 19:02:14 (GMT) |
commit | 1285c9b7829a6ae3a1267e7676b1bc2c5ce11f96 (patch) | |
tree | 50e50f3d539ca7b4463bed0926d8ff0cf6927683 /Lib/concurrent | |
parent | 26795baaa812c74087e97f9119ec143451e23daa (diff) | |
download | cpython-1285c9b7829a6ae3a1267e7676b1bc2c5ce11f96.zip cpython-1285c9b7829a6ae3a1267e7676b1bc2c5ce11f96.tar.gz cpython-1285c9b7829a6ae3a1267e7676b1bc2c5ce11f96.tar.bz2 |
Issue #21817: When an exception is raised in a task submitted to a ProcessPoolExecutor, the remote traceback is now displayed in the parent process.
Patch by Claudiu Popa.
Diffstat (limited to 'Lib/concurrent')
-rw-r--r-- | Lib/concurrent/futures/process.py | 26 |
1 files changed, 24 insertions, 2 deletions
diff --git a/Lib/concurrent/futures/process.py b/Lib/concurrent/futures/process.py index fc64dbe..3dd6da1 100644 --- a/Lib/concurrent/futures/process.py +++ b/Lib/concurrent/futures/process.py @@ -57,6 +57,7 @@ import threading import weakref from functools import partial import itertools +import traceback # Workers are created as daemon threads and processes. This is done to allow the # interpreter to exit when there are still idle processes in a @@ -90,6 +91,27 @@ def _python_exit(): # (Futures in the call queue cannot be cancelled). EXTRA_QUEUED_CALLS = 1 +# Hack to embed stringification of remote traceback in local traceback + +class _RemoteTraceback(Exception): + def __init__(self, tb): + self.tb = tb + def __str__(self): + return self.tb + +class _ExceptionWithTraceback: + def __init__(self, exc, tb): + tb = traceback.format_exception(type(exc), exc, tb) + tb = ''.join(tb) + self.exc = exc + self.tb = '\n"""\n%s"""' % tb + def __reduce__(self): + return _rebuild_exc, (self.exc, self.tb) + +def _rebuild_exc(exc, tb): + exc.__cause__ = _RemoteTraceback(tb) + return exc + class _WorkItem(object): def __init__(self, future, fn, args, kwargs): self.future = future @@ -152,8 +174,8 @@ def _process_worker(call_queue, result_queue): try: r = call_item.fn(*call_item.args, **call_item.kwargs) except BaseException as e: - result_queue.put(_ResultItem(call_item.work_id, - exception=e)) + exc = _ExceptionWithTraceback(e, e.__traceback__) + result_queue.put(_ResultItem(call_item.work_id, exception=exc)) else: result_queue.put(_ResultItem(call_item.work_id, result=r)) |