Skip to content

Instantly share code, notes, and snippets.

@jomido
Last active March 14, 2017 14:47
Show Gist options
  • Save jomido/c22879458b64b74f165843f5bc00a66c to your computer and use it in GitHub Desktop.
Save jomido/c22879458b64b74f165843f5bc00a66c to your computer and use it in GitHub Desktop.
Async By Default
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()
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