简体   繁体   English

Python:等待发电机结束

[英]Python: await the generator end

Current versions of Python (Dec 2022) still allow using @coroutine decorator and a generation can be as: Python(2022 年 12 月)的当前版本仍然允许使用 @coroutine 装饰器,生成可以是:

import asyncio
asyncify = asyncio.coroutine
data_ready = False # Status of a pipe, just to test

def gen():
    global data_ready

    while not data_ready:
        print("not ready")
        data_ready = True # Just to test
        yield

    return "done"

async def main():
    result = await asyncify(gen)()
    print(result)

loop = asyncio.new_event_loop()
loop.create_task(main())
loop.run_forever()

However, new Python versions 3.8+ will deprecate @coroutine decorator (the asyncify function alias), how to wait for (await) generator to end as above ?然而,新的 Python 版本 3.8+ 将弃用 @coroutine 装饰器( asyncify function 别名),如何等待(await)生成器结束如上

I tried to use async def as expected by the warning but not working:我尝试按照警告的预期使用async def但没有工作:

import asyncio
asyncify = asyncio.coroutine
data_ready = False # Just to test

async def gen():
    global data_ready

    while not data_ready:
        print("not ready")
        data_ready = True # Just to test
        yield

    yield "done"
    return

async def main():
    # this has error: TypeError: object async_generator can't be used in 'await' expression
    result = await gen()
    print(result)

loop = asyncio.new_event_loop()
loop.create_task(main())
loop.run_forever()

Asynchronous generators inherit asynchronous iterator and are aimed for asynchronous iterations.异步生成器继承异步迭代器,针对异步迭代。
You can not directly await them as regular coroutines.您不能像常规协程一样直接await它们。
With that in mind, returning to your experimental case and your question "how to wait for (await) generator to end?"考虑到这一点,回到你的实验案例和你的问题“如何等待(await)生成器结束?” : to get the final yield ed value - perform asynchronous iterations: : 获得最终的yield ed 值 - 执行异步迭代:

import asyncio

data_ready = False # Just to test

async def gen():
    global data_ready
    while not data_ready:
        print("not ready")
        data_ready = True # Just to test
        yield "processing"
    yield "done"
    return


async def main():
    a_gen = gen()
    async for result in a_gen:  # assign to result on each async iteration
        pass
    print('result:', result)

asyncio.run(main())

Prints:印刷:

not ready
result: done

Naturally, you can also advance the async generator in steps with anext :当然,您也可以使用anext推进异步生成器:

a_gen = gen()
val_1 = await anext(a_gen)

Summing up, follow the guidlines on PEP 525 – Asynchronous Generators and try to not mix old-depreceted things with the actual ones.总而言之,请遵循PEP 525 – 异步生成器中的指南,并尽量不要将过时的东西与实际的东西混在一起。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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