2017-12-11 10 views
3

어딘가에서 메시지를받는 버스가 있다고 가정 해 보겠습니다. 모든 메시지는 targetmsg 있고, 내가 가입 mecahnism을 구현하려는, 그래서 다른 코 루틴 할 수있는 특정 targetasyncio send가 호출 될 때까지 coroutine을 일시 중지하는 방법

subscriptions = {} 
async def subscribe(target): 
    subscriptions[target]= wait_for_messages() 

async def proc_msg(target,msg); 
    subscriptions[target].send(msg) 

async def wait_for_messages(): 
    while True: 
     asyncio.sleep(1) 

async def subscribe(target) 
    async for msg in subscribe(target): 
     print(msg) 

내 질문의 wait_for_messages 관련되는 subscribe 비록 작품의 수면 종류 (코드 프리젠 테이션 용으로 만), 어떻게 자고 끊지 않고 끊임없이 send 명령을 기다릴 수 있습니까?

답변

2

가입 메커니즘은 콜백 세계에서 제공되며 asyncio.Future은 콜백 기반의 세계에서부터 코 루틴 기반의 세계에 이르기까지 일종의 다리입니다. 그걸로 뭔가 일이 생길 때까지 기다릴 수 있습니다. 메시지 수신시 set_result을 사용하고 미래 메시지 수신시 await을 사용하여 coroutine 내부 메시지를 수신하십시오.

import asyncio 
from random import randint 
from collections import defaultdict 
from contextlib import suppress 


# MSG SUBSCRIBE/SEND API: 
_futures = defaultdict(asyncio.Future) 


async def msg_for_target(target): 
    """Await for this coroutine to recieve msg.""" 
    return await _futures[target] 


def send_msg(target, msg): 
    _futures[target].set_result(msg) 
    del _futures[target] # We would need new Future for future subscribers 


# TEST: 
async def random_sender(): 
    """Send random messages.""" 
    i = 0 
    while True: 
     i += 1 
     await asyncio.sleep(0.5) 

     target = randint(0, 3) 
     msg = f'msg {i}'   
     print(f'Sending msg "{msg}" for target "{target}" ...') 
     send_msg(target, msg) 


async def main(): 
    task = asyncio.ensure_future(random_sender()) 

    for target in (2, 0, 3, 1): 
     print(f'> Subscribed for target "{target}"') 
     msg = await msg_for_target(target) 
     print(f'> Recieved "{msg}"') 
     print() 

    # Cleanup, see https://stackoverflow.com/a/43810272/1113207 
    task.cancel() 
    with suppress(asyncio.CancelledError): 
     await task 


if __name__ == '__main__': 
    loop = asyncio.get_event_loop() 
    try: 
     loop.run_until_complete(main()) 
    finally: 
     loop.run_until_complete(loop.shutdown_asyncgens()) 
     loop.close() 

출력 :

> Subscribed for target "2" 
Sending msg "msg 1" for target "2" ... 
> Recieved "msg 1" 

> Subscribed for target "0" 
Sending msg "msg 2" for target "3" ... 
Sending msg "msg 3" for target "0" ... 
> Recieved "msg 3" 

> Subscribed for target "3" 
Sending msg "msg 4" for target "2" ... 
Sending msg "msg 5" for target "2" ... 
Sending msg "msg 6" for target "2" ... 
Sending msg "msg 7" for target "1" ... 
Sending msg "msg 8" for target "3" ... 
> Recieved "msg 8" 

> Subscribed for target "1" 
Sending msg "msg 9" for target "0" ... 
Sending msg "msg 10" for target "0" ... 
Sending msg "msg 11" for target "2" ... 
Sending msg "msg 12" for target "2" ... 
Sending msg "msg 13" for target "1" ... 
> Recieved "msg 13"