python异步通信_Python异步:阅读器回调和协程通信

I am trying to implement a simple idea of passing a data from stdin to a coroutine:

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()

This code works fine, however a simplified version of it with a variable instead of an Event object works too:

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

My questions are: is the approach with Event correct? Or is there a better way with another asyncio objects to handle this kind of problem?

Then, if the approach with Event is fine, is using a variable is fine as well?

Thank you.

解决方案

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.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值