Skip to content

Instantly share code, notes, and snippets.

@karatheodory
Forked from schlamar/processify.py
Last active May 30, 2017 06:21
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save karatheodory/e5dbeeccc54010a599c8d15c723c17eb to your computer and use it in GitHub Desktop.
Save karatheodory/e5dbeeccc54010a599c8d15c723c17eb to your computer and use it in GitHub Desktop.
processify
import sys
import traceback
from functools import wraps
from multiprocessing import Process, Queue
def processify(func):
"""
Decorator to run a function as a process.
Be sure that every argument and the return value
is *pickable*.
The created process is joined, so the code does not
run in parallel.
"""
def process_func(q, *args, **kwargs):
# noinspection PyBroadException
try:
ret = func(*args, **kwargs)
except Exception:
ex_type, ex_value, tb = sys.exc_info()
error = ex_type, ex_value, ''.join(traceback.format_tb(tb))
ret = None
else:
error = None
q.put((ret, error))
# register original function with different name
# in sys.modules so it is pickable
process_func.__name__ = func.__name__ + 'processify_func'
setattr(sys.modules[__name__], process_func.__name__, process_func)
@wraps(func)
def wrapper(*args, **kwargs):
q = Queue()
p = Process(target=process_func, args=[q] + list(args), kwargs=kwargs)
p.start()
ret, error = q.get()
p.join()
if error:
ex_type, ex_value, tb_str = error
message = '%s (in subprocess)\n%s' % (ex_value.message, tb_str)
# noinspection PyBroadException
try:
exception = ex_type(message)
except Exception:
# Failed to keep the original exception type
exception = Exception('%s\n(original exception type: %s)' % (message, ex_type))
raise exception
return ret
return wrapper
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment