【问题标题】:What is an 'async_generator' & how is it different from a 'coroutine' in Python 3.6?什么是“async_generator”以及它与 Python 3.6 中的“协程”有何不同?
【发布时间】:2018-01-25 00:44:55
【问题描述】:

我怀疑这与 b/w yield fromawait 的差异有关。 但是,除了将新对象指定为async_generator 之外,我不清楚它与coroutine 之间差异的后果。 (除了我在标题中提出的问题,我不知道还能问什么问题......)

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()))

这给出了:

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


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

我无法判断这个...

【问题讨论】:

  • 生成器yields,协程没有。
  • 这是两者的唯一区别吗?

标签: python asynchronous generator python-asyncio coroutine


【解决方案1】:

为了anasync_generator-生成函数在事件循环中运行,其输出必须包装在coroutine.

这是为了防止async_generator 将值直接生成到事件循环中。


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)]))

只像任务和未来一样循环。

如果一个循环接收到一个整数或字符串,或者......任何不是从其任务之一的future 派生的东西,它将中断。

因此coroutines 必须:

  • 产生futures(或future的子类,)
  • 或不将任何值传回循环。

这里是 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()

这是输出:

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'>

【讨论】:

    猜你喜欢
    • 2016-12-09
    • 2013-03-23
    • 2012-02-09
    • 2020-01-08
    • 2018-11-09
    • 1970-01-01
    • 2013-08-02
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多