Python asyncio: reader callback and coroutine communication

为君一笑 提交于 2019-11-30 18:35:13
dano

I think asyncio.Queue is much better suited for this kind of producer/consumer relationship:

import asyncio
import sys

queue = asyncio.Queue()

def handle_stdin():
    data = sys.stdin.readline()
    # Queue.put is a coroutine, so you can't call it directly.
    asyncio.async(queue.put(data)) 
    # Alternatively, Queue.put_nowait() is not a coroutine, so it can be called directly.
    # queue.put_nowait(data)

async def tick():
    while 1:
        data = await queue.get()
        print('Data received: {}'.format(data))

def main(): 
    loop = asyncio.get_event_loop()
    loop.add_reader(sys.stdin, handle_stdin)
    loop.run_until_complete(tick())    

if __name__ == '__main__':
    main()

There's less logic involved than with an Event, which you need to make sure you set/unset properly, and there's no need for a sleep, wakeup, check, go back to sleep, loop, like with the global variable. So the the Queue approach is simpler, smaller, and blocks the event loop less than your other possible solutions. The other solutions are technically correct, in that they will function properly (as long as you don't introduce any yield from calls inside if if event.is_set() and if data is not None: blocks). They're just a bit clunky.

If you want to wait for an event, you should probably be using Event.wait instead of polling is_set.

@asyncio.coroutine
def tick():
    while True:
        yield from event.wait()
        print('Data received: {}'.format(event.data))
        event.clear()
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!