代码之家  ›  专栏  ›  技术社区  ›  unsafe_where_true

python:等待从套接字读取或在事件发生时关闭

  •  0
  • unsafe_where_true  · 技术社区  · 11 月前

    给定此函数:

    async def read_data(self, stream: UStreams) -> None:
        while True:
            read_bytes = await stream.read(MAX)
            #handle the bytes  
    

    当然,这将使函数永远运行。

    我想让这个函数这样做,但也要在发生事件时关闭(因此退出函数):

    async def read_data(self, stream: UStreams, evt: trio.Event) -> None:
        while True:
            read_bytes = await stream.read(MAX) || await evt.wait() # <- how do I do this?
            #handle the bytes or exit
    

    我不能简单地说 evt.wait() 作为循环中的第一个语句,因为流永远不会被读取(另一种方式也不起作用,因为如果没有要读取的内容,则永远不会等待事件)。 gather 代码类型也没有帮助,我不想同时等待:只等待第一个出现(在 go 这将通过 select 陈述

    1 回复  |  直到 11 月前
        1
  •  1
  •   sytech    11 月前

    您可以使用其中一个 waiting primitives 例如 asyncio.wait asyncio.as_completed .

    import asyncio
    
    async def select(*awaitables):
        return await next(asyncio.as_completed(awaitables))
    

    实例

    async def fast():
        await asyncio.sleep(0.2)
        return 1
    
    async def slow():
       await asyncio.sleep(1)
       return 2
    
    async def main():
        result = await select(fast(), slow())
        print(result)
    
    asyncio.run(main())
    # 1
    

    在三人组中,您也可以使用 supervisor 。从文档中:

    这里有一个函数,它接受一个函数列表,同时运行所有函数,并从第一个完成的函数返回结果:

    async def race(*async_fns):
        if not async_fns:
            raise ValueError("must pass at least one argument")
    
        winner = None
    
        async def jockey(async_fn, cancel_scope):
            nonlocal winner
            winner = await async_fn()
            cancel_scope.cancel()
    
        async with trio.open_nursery() as nursery:
            for async_fn in async_fns:
                nursery.start_soon(jockey, async_fn, nursery.cancel_scope)
    
        return winner
    

    这是通过启动一组任务来实现的,每个任务都试图运行各自的功能。一旦第一个函数完成执行,任务就会设置非局部变量 winner 从外部范围到函数的结果,并使用传入的取消范围取消其他任务。一旦所有任务都被取消(这将退出托儿所块),变量 赢家 将被退回。

    推荐文章