简体   繁体   中英

What is an 'async_generator' & how is it different from a 'coroutine' in Python 3.6?

I suspect this has something to do with the differences b/w yield from & await . However, & aside from the new object's designation as an async_generator , I'm unclear about consequences regarding the differences between it and a coroutine . (I'm not sure how else to ask the question other than the one I put in the title...)

import asyncio

async def async_generator_spits_out_letters():
    yield 'a'
    yield 'b'
    yield 'c'
    yield 'd'
    await asyncio.sleep(0)

async def coroutine_prints_messages():
    while True:
        print('hi')
        await asyncio.sleep(2)

def test_it():
    print(type(async_generator_spits_out_letters))
    print(type(coroutine_prints_messages))
    # This is how I choose to do newlines....it's easier for me to read. :[
    print(); print()

    print(type(async_generator_spits_out_letters()))
    print(type(coroutine_prints_messages()))

This gives:

<class 'async_generator'>
<class 'coroutine'>


<class 'function'>
<class 'function'>

I can't make heads or tails of this...

In order for an async_generator -producing function to run in an eventloop, its output must be wrapped in a coroutine.

This is to prevent the async_generator from yielding values directly INTO the event-loop.


 import asyncio # This produces an async_generator async def xrange(numbers): for i in range(numbers): yield i await asyncio.sleep(0) # This prevents an async_generator from yielding into the loop. async def coroutine_wrapper(async_gen, args): try: print(tuple([i async for i in async_gen(args)])) except ValueError: print(tuple([(i, j) async for i, j in async_gen(args)]))

Loops only like tasks & futures.

If a loop receives an integer or string or..anything not derived from a future from one of its tasks, it will break.

Therefore coroutines must either:

  • produce future s (or subclasses of future ,)
  • OR NOT pass any values back into the loop.

Here's main():

 def main(): print('BEGIN LOOP:') print() loop = asyncio.get_event_loop() xrange_iterator_task = loop.create_task(coroutine_wrapper(xrange, 20)) try: loop.run_until_complete(xrange_iterator_task) except KeyboardInterrupt: loop.stop() finally: loop.close() print() print('END LOOP') print(); print() print('type(xrange) == {}'.format(type(xrange))) print('type(xrange(20) == {}'.format(type(xrange(20)))) print() print('type(coroutine_wrapper) == {}'.format(type(coroutine_wrapper))) print('type(coroutine_wrapper(xrange,20)) == {}'.format(type(coroutine_wrapper(xrange, 20)))) if __name__ == '__main__': main()

Here's the output:

 BEGIN LOOP: (0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19) END LOOP type(xrange) == <class 'function'> type(xrange(20)) == <class 'async_generator'> type(coroutine_wrapper) == <class 'function'> type(coroutine_wrapper(xrange,20)) == <class 'coroutine'>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM