2015-05-31 39 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()