Created
February 11, 2019 08:58
-
-
Save EddieIvan01/76e6dc24223c34c3d3f4ea4c25ab53e2 to your computer and use it in GitHub Desktop.
async function decorator
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from functools import wraps | |
from threading import Thread | |
from queue import Queue | |
class Async(object): | |
__slots__ = ('__result', '__task') | |
def __init__(self, func): | |
self.__result = Queue() | |
@wraps(func) | |
def wrapper(*args, **kw): | |
r = func(*args, **kw) | |
self.__result.put(r) | |
self.__task = wrapper | |
def __call__(self, *args, **kw): | |
thread = Thread(target=self.__task, args=args, kwargs=kw) | |
thread.start() | |
return Async.Result(self.__result, thread) | |
class Result(object): | |
def __init__(self, q, t): | |
self.__queue = q | |
self.__thread = t | |
def is_done(self): | |
return not self.__thread.is_alive() | |
def _get_r(self): | |
if not self.is_done(): | |
raise Exception('Not done yet') | |
if not hasattr(self, '_result'): | |
self._result = self.__queue.get() | |
return self._result | |
def _set_r(self, v): | |
self._result = v | |
result = property(_get_r, _set_r) | |
del _get_r, _set_r | |
if __name__ == '__main__': | |
import time | |
import requests | |
@Async | |
def count(n): | |
time.sleep(n) | |
return f'sleep {n} done' | |
@Async | |
def http(url): | |
r = requests.get(url) | |
return r.text | |
start = time.time() | |
r1 = count(10) | |
r2 = count(5) | |
r3 = http('http://www.baidu.com') | |
r4 = http('http://b.cn') | |
for i in range(20): | |
print(f'call {i}') | |
time.sleep(1) | |
if r1.is_done(): | |
print(r1.result) | |
if r2.is_done(): | |
print(r2.result) | |
if r3.is_done(): | |
print(r3.result) | |
r3.result = 'r3 done' | |
if r4.is_done(): | |
print(r4.result) | |
r4.result = 'r4 done' | |
if r1.is_done() and r2.is_done() and r3.is_done() and r4.is_done(): | |
break | |
end = time.time() | |
print(end-start) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment