【问题标题】:How to convert callback-based async function to async generator如何将基于回调的异步函数转换为异步生成器
【发布时间】:2017-04-29 18:22:07
【问题描述】:

目前可以通过提供在每个传入连接上触发的回调来启动异步服务器:

async def on_connection(reader, writer):
    # this is invoked each time a new connection is made
    pass

server = await asyncio.start_server(on_connection, host, port)

我想摆脱回调并改用async for,所以它看起来像这样:

async for reader, writer in my_start_server(host, port):
    # this should be invoked each time a new connection is made
    pass

不幸的是,这似乎并不容易:

async def my_start_server(host, port):
    async def on_connection(reader, writer):
        # here I have to somehow yield (reader, writer) tuple
        # but if I do just `yield (reader, writer)`, it would 
        # make `on_connection` itself a generator, but would 
        # not affect `my_start_server`
        pass

    server = await asyncio.start_server(on_connection, host, port)

我曾想过在那里有一个带有__aiter__ 实现的类,但结果似乎过于复杂了很多。那么,这是唯一的方法吗,还是我错过了将异步回调转换为异步生成器的任何简单方法?

【问题讨论】:

  • 通常,您希望能够同时处理多个客户端。 async for 方法不允许这样做。
  • @Vincent,嗯,你似乎是对的 - async for 不会从服务器获取下一个连接,直到你完成处理当前连接。我希望 async for 具有“尽快消费”语义。

标签: python python-3.x asynchronous python-asyncio asynccallback


【解决方案1】:

正如文森特所注意到的,您不应该使用async for 来获取连接,因为其中的代码会阻止其他连接的处理。将每个连接视为应运行的单独任务,而不管其他连接。

这里有一个例子,你可以在my_start_server 中使用队列yield,这也表明我们仍然会返回某种on_connection

async def my_start_server(host, port):
    queue = asyncio.Queue()

    async def put(reader, writer):
        await queue.put((reader, writer,))

    await asyncio.start_server(put, host, port)

    while True:
        yield (await queue.get())

.

async for (reader, writer) in my_start_server(host, port):

    # If we will just handle reader/writer here, others will be suspended from handling.
    # We can avoid it starting some task,
    # but in this case 'handle' would be nothing different from 'on_connection'

    asyncio.Task(handle(reader, writer))

【讨论】:

    猜你喜欢
    • 2018-11-24
    • 2015-05-30
    • 2019-08-17
    • 1970-01-01
    • 2017-10-22
    • 2015-06-25
    • 2020-08-17
    • 1970-01-01
    相关资源
    最近更新 更多