2015-05-31 36 views
5

我在理解如何将新任务挂起到已经运行的事件循环时遇到问题。了解asyncio已经永久运行循环和待处理任务

此代码:

import asyncio 
import logging 

@asyncio.coroutine 
def blocking(cmd): 
    while True: 
     logging.info("in blocking coroutine") 
     yield from asyncio.sleep(0.01) 
     print("ping") 

def main(): 
    logging.info("in main funciton") 
    loop = asyncio.get_event_loop() 
    logging.info("new loop created") 
    logging.info("loop running forever") 
    loop.run_forever() 
    asyncio.async(blocking("ls")) 

logging.basicConfig(level = logging.INFO) 
main() 

更改run_forever()run_until_complete(asyncio.async(blocking("ls"))工作正常。但是我很困惑 - 为什么我不能在已经运行的循环上挂任务?

回答

10

问题是拨打loop.run_forever()块;它会启动事件循环,并且直到您明确停止循环才会返回 - 因此run_foreverforever部分。您的程序从不明确停止事件循环,因此您的呼叫永远不会到达。

使用asyncio.async添加一个新的任务到一个已经运行的循环没问题,你只需要确保该函数实际上是从协程内部或事件循环内部的回调中调用的。下面是一些例子:

附表blocking为事件循环即开始运行:

def main(): 
    logging.info("in main funciton") 
    loop = asyncio.get_event_loop() 
    logging.info("new loop created") 
    logging.info("loop running forever") 
    asyncio.async(blocking("ls")) 
    loop.run_forever() 

附表blocking从事件循环执行的回调:

def start_blocking(): 
    asyncio.async(blocking("ls")) 

def main(): 
    logging.info("in main funciton") 
    loop = asyncio.get_event_loop() 
    logging.info("new loop created") 
    logging.info("loop running forever") 
    loop.call_soon(start_blocking) # Calls start_blocking once the event loop starts 
    loop.run_forever()