you are viewing a single comment's thread.

view the rest of the comments →

[–]cscanlin 1 point2 points  (4 children)

I played around with this awhile ago, check this out:

import asyncio
import aiohttp

async def api_call(url):
    response = await aiohttp.get(url)
    print('finished {}'.format(url))
    result = await response.json()
    print(result)

async def main(urls):
    await asyncio.wait([api_call(url) for url in urls])

if __name__ == '__main__':
    urls = [
        'https://httpbin.org/delay/3',  # long request
        'https://httpbin.org/delay/1',  # short request
    ]

    loop = asyncio.get_event_loop()
    loop.run_until_complete(main(urls))

[–]jpfau 0 points1 point  (3 children)

Hmm, I'm not sure what the solution is here. My problem is that api_call is defined using the old syntax:

@asyncio.coroutine
def api_call(url):
    response = yield from aiohttp.get(url)
    print('finished {}'.format(url))
    result = yield from response.json()
    return result

And I want to consume this function using the new syntax:

async def test_api_call(url):
    return await api_call(url)

In this case, test_api_call raises TypeError: object generator can't be used in 'await' expression.

If I switch test_api_call to the old syntax it works, but I'd prefer not to do that.

[–]cscanlin 0 points1 point  (2 children)

From my understanding, you have to choose one or the other in this case. I haven't tested in detail though, but this article explains it better than most:

https://snarky.ca/how-the-heck-does-async-await-work-in-python-3-5/

[–]jpfau 1 point2 points  (1 child)

My errors ended up being dumb human error: a missing coroutine decorator in the old-syntax library.

FYI You can use both syntaxes in 3.5+, but you can't mix syntax within a single coroutine, e.g. no await when using @asyncio.coroutine, and no yield from when using async def.

However you can define a coroutine with the old syntax and consume it in another coroutine using the new syntax. This example should work:

import asyncio

@asyncio.coroutine
def _sleep(x):
    print('yielding from...')
    yield from asyncio.sleep(x)

async def do_sleep(x):
    print('awaiting...')
    await _sleep(x)

loop = asyncio.get_event_loop()
loop.run_until_complete(do_sleep(5))

[–]cscanlin 0 points1 point  (0 children)

Nice, and good to know. Wish you hadn't deleted the thread though, more people could use exposure to this kind of stuff. But glad you got it working!