了解asyncio已经永远运行循环和待处理任务

use*_*992 6 python python-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 Code Online (Sandbox Code Playgroud)

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

dan*_*ano 11

问题是对loop.run_forever()块的调用; 它启动事件循环,直到你明确停止循环才会返回 - 因此是forever部分run_forever.您的程序永远不会明确停止事件循环,因此您的asyncio.async(blocking("ls"))呼叫永远不会到达.

使用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()
Run Code Online (Sandbox Code Playgroud)

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()
Run Code Online (Sandbox Code Playgroud)