Skip to content

Instantly share code, notes, and snippets.

@phizaz
Last active May 19, 2019 00:35
Show Gist options
  • Save phizaz/dc45756db1197cee83bbdfa964a1b46a to your computer and use it in GitHub Desktop.
Save phizaz/dc45756db1197cee83bbdfa964a1b46a to your computer and use it in GitHub Desktop.
Python CatchableProcess: Catch exceptions in spawned processes
from multiprocessing import Process
class CatchableProcess(Process):
def __init__(self, target, args=[], kwargs=dict()):
from multiprocessing import Queue
self.error = Queue(1)
self.result = Queue(1)
def wrapper(target, args, kwargs):
try:
res = target(*args, **kwargs)
self.result.put(res)
except Exception as e:
self.error.put(e)
raise
super(CatchableProcess, self).__init__(target=wrapper,
kwargs=dict(
target=target,
args=args,
kwargs=kwargs
))
def join(self, timeout=None):
super(CatchableProcess, self).join(timeout)
if not self.error.empty():
raise self.error.get()
if not self.result.empty():
return self.result.get()
else:
return None
import unittest
from catchableprocess import CatchableProcess
class CatchableProcessTest(unittest.TestCase):
def test_catchable_process(self):
def dummy():
raise Exception('should be catched')
p = CatchableProcess(target=dummy)
p.start()
self.assertRaises(p.join)
def test_normal_process(self):
def dummy():
return 10
p = CatchableProcess(target=dummy)
p.start()
self.assertEqual(p.join(), 10)
def test_normal_process_with_none_response(self):
def dummy(): pass
p = CatchableProcess(target=dummy)
p.start()
self.assertIsNone(p.join())
def test_get_pid(self):
def dummy(): pass
p = CatchableProcess(target=dummy)
p.start()
self.assertIsInstance(p.pid, int)
p.join()
def test_terminate(self):
def dummy():
import time
time.sleep(1)
raise Exception('should be killed long before')
p = CatchableProcess(target=dummy)
p.start()
p.terminate()
p.join()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment