Last active
March 14, 2017 14:47
-
-
Save jomido/c22879458b64b74f165843f5bc00a66c to your computer and use it in GitHub Desktop.
Async By Default
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
import asyncio | |
import aiohttp | |
import time | |
from utils import start, auto | |
class Context(object): | |
def __init__(self, **kwargs): | |
self.__dict__.update(**kwargs) | |
@auto | |
async def program_a(context): | |
session = aiohttp.ClientSession() | |
while True: | |
try: | |
msg = context.inbox.get_nowait() | |
except asyncio.QueueEmpty: | |
msg = None | |
if msg: | |
break | |
begin = time.time() | |
async with session.get(context.url) as response: | |
result = await response.json() | |
context.outbox.put_nowait(len(result)) | |
duration = time.time() - begin | |
sleep_time = context.interval - duration | |
await asyncio.sleep(max(1, sleep_time)) | |
print('also quitting') | |
session.close() | |
context.loop.stop() | |
@auto | |
async def program_b(context): | |
no_msgs = 0 | |
while True: | |
msg = await context.inbox.get() | |
no_msgs += 1 | |
print(msg) | |
if no_msgs == 3: | |
context.outbox.put_nowait(1) | |
print('quiting') | |
break | |
@auto | |
def say_hello(): | |
print('hi!') | |
if __name__ == "__main__": | |
loop = asyncio.get_event_loop() | |
mailbox_a = asyncio.Queue() | |
mailbox_b = asyncio.Queue() | |
a_program_a = program_a(Context( | |
interval=2, | |
url='https://api.github.com/events', | |
inbox=mailbox_a, | |
outbox=mailbox_b, | |
loop=loop | |
)) | |
a_program_b = program_b(Context( | |
inbox=mailbox_b, | |
outbox=mailbox_a | |
)) | |
say_hello() | |
loop.run_forever() |
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
import asyncio | |
from functools import wraps | |
def maybeAsync(callable, *args, **kwargs): | |
""" | |
Turn a callable into a coroutine if it isn't | |
""" | |
if asyncio.iscoroutine(callable): | |
return callable | |
return asyncio.coroutine(callable)(*args, **kwargs) | |
def start(callable, *args, **kwargs): | |
""" | |
Start a callable as a coroutine, and return it's future. The cool thing | |
about this function is that (via maybeAsync) it lets you treat synchronous | |
and asynchronous callables the same (both as async), which simplifies code. | |
""" | |
return asyncio.ensure_future(maybeAsync(callable, *args, **kwargs)) | |
def auto(fn): | |
""" | |
Decorate a function or method with this, and it will become a callable | |
that can be scheduled in the event loop just by calling it. Normally you'd | |
have to do an `asyncio.ensure_future(my_callable())`. Not you can just do | |
`my_callable()`. Twisted has always let you do this, and now you can let | |
asyncio do it as well (with a decorator, albeit...) | |
""" | |
@wraps(fn) | |
def wrapper(*args, **kwargs): | |
return start(fn, *args, **kwargs) | |
return wrapper |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment