Garciat
7/24/2017 - 4:04 PM

out_of_process.py

def out_of_process(func):
    from types import GeneratorType
    GENERATOR = b'#GENERATOR#'
    DONE = b'#DONE#'

    def runner(conn, *args, **kwargs):
        return_value = func(*args, **kwargs)
        if isinstance(return_value, GeneratorType):
            conn.send(GENERATOR)
            for val in return_value:
                conn.put(val)
            conn.send(DONE)
        else:
            conn.put(return_value)
        conn.close()

    def multi_value(proc, return_queue):
        while True:
            value = return_queue.get()
            if isinstance(value, bytes) and value == DONE:
                break
            yield value

    def wrapper(*args, **kwargs):
        return_queue = Queue()
        args = (return_queue,) + args

        proc = Process(target=runner, args=args, kwargs=kwargs)
        proc.start()

        return_value = return_queue.get()

        if isinstance(return_value, bytes) and return_value == GENERATOR:
            return multi_value(proc, return_queue)
        else:
            proc.join()
            return return_value

    return wrapper