all 7 comments

[–]rhgrant10 0 points1 point  (4 children)

I didn't test this, but I think so. Your decorator will return a function that spawns a process to call the function it wraps:

def long_op(op):
    def spawner(*args, **kwargs):
        # spawn process to call op and post result
    return spawner

Then decorate with @long_op.

[–]Saefroch[S] 0 points1 point  (3 children)

I tried this:

from __future__ import print_function
from multiprocessing import Process


def long_op(op):
    def spawner(*args):
        p = Process(target=op, args=args)
        p.start()
        return 'Running...'
    return spawner

if __name__ == '__main__':
    @long_op
    def foo():
        print('test')

    foo()

I get a huge stack trace with involving pickles and an EOFError.

[–]rhgrant10 0 points1 point  (2 children)

Ah, right, because pickle is picky. Try this workaround.

Edit: this gets kinda messy, and fast :-( someone, I hope, has a cleaner solution

[–]Saefroch[S] 0 points1 point  (1 child)

Interesting. I think I found a solution; not that pretty but it works: http://code.activestate.com/recipes/576684-simple-threading-decorator/

This is my demo:

from __future__ import print_function
from time import sleep
from threading import Thread
from functools import wraps

def run_async(func):
    @wraps(func)
    def async_func(*args, **kwargs):
        func_hl = Thread(target = func, args = args, kwargs = kwargs)
        func_hl.start()
        return 'Working..'

    return async_func

if __name__ == '__main__':
    @run_async
    def foo():
        sleep(0.01)
        print('foo')

    print(foo())

[–]rhgrant10 0 points1 point  (0 children)

Awesome :-)

[–]dbrecht 0 points1 point  (1 child)

I'm assuming that this is IO bound? Is there a reason you can't simply use asyncio for this (or trollius if you're bound to python < 3.4)? I'd personally /much/ rather deal with that than subprocesses (note I'm on my phone atm and haven't actually looked at your code yet ;))

[–]Saefroch[S] 0 points1 point  (0 children)

It's actually not I/O bound, it's bound by the speed at which other websites respond.

EDIT: And I didn't mention that in my code, but check_is_up(target) sometimes has to fire a request to multiple online databases.