如何解决Python异步:阅读器回调和协程通信
我认为asyncio.Queue
更适合这种生产者/消费者关系:
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()
与相比,所需的逻辑更少Event
,您需要确保正确设置/取消设置,并且无需sleep
像全局变量那样进行唤醒,检查,返回睡眠,循环等操作。因此,该Queue
方法比其他可能的解决方案更简单,更小,并且对事件循环的阻塞更少。其他解决方案在技术上是正确的 ,因为它们可以正常运行(只要您yield from
在ifif event.is_set()
和if data is not
None:
block内不引入任何调用)。他们只是笨拙。
解决方法
我试图实现一个简单的想法,将数据从stdin传递到协程:
import asyncio
import sys
event = asyncio.Event()
def handle_stdin():
data = sys.stdin.readline()
event.data = data # NOTE: data assigned to the event object
event.set()
@asyncio.coroutine
def tick():
while 1:
print('Tick')
yield from asyncio.sleep(1)
if event.is_set():
data = event.data # NOTE: data read from the event object
print('Data received: {}'.format(data))
event.clear()
def main():
loop = asyncio.get_event_loop()
loop.add_reader(sys.stdin,handle_stdin)
loop.run_until_complete(tick())
if __name__ == '__main__':
main()
这段代码可以正常工作,但是使用变量而不是Event
对象的简化版本也可以工作:
data = None
def handle_stdin():
global data
data = sys.stdin.readline()
@asyncio.coroutine
def tick():
while 1:
print('Tick')
yield from asyncio.sleep(1)
global data
if data is not None:
print('Data received: {}'.format(data))
data = None
我的问题是:这种方法Event
正确吗?还是有另一个更好的方法与另一个异步对象来处理这种问题?然后,如果使用的方法Event
很好,那么使用变量也可以吗?
谢谢。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。