原文出自:Asyncio Event Loops Tutorial

任何基于asyncio的Python程序的主要组件都必须是底层的事件循环。在这个事件循环中,我们可以(来自官方文档):

  1. 注册,执行和取消调用

  2. 启动子进程和关联的传输以与外部程序进行通信

  3. 将代价高昂的函数调用委托给线程池


基本上所有事件循环都是等待事件发生,然后将每个事件匹配到我们已经明确匹配所述事件类型的函数。


一个很好的例子是一个简单的Web服务器,比如说我们的服务器上有一个Web端,它为我们的网站提供了大量不同的页面。我们的事件循环基本上监听请求,然后将这些请求中的每一个与其关联的网页进行匹配。

在上面的示例中对我们的Web服务器发出的每个请求都将被视为一个单独的 event 。然后,这些事件与我们在触发所述事件时预定义的集合函数匹配。

入门:

让我们快速看看如何定义一个非常简单的事件循环。为了实例化一个事件循环,我们将使用asyncio.get_event_loop()

将其包裹在try… finally 我们将指定我们希望新实例化的事件循环运行,直到它完成 myCoroutine() 函数。

import asyncio

# 定义一个想要被执行的协程
async def my_coroutine():
    print("my_coroutine")

# 启动快速简单的事件循环并运行直到完成
loop = asyncio.get_event_loop()
try:
   loop.run_until_complete(my_coroutine())
finally:
   loop.close()
其他运行的参数

我们有许多运行事件循环的选项,我们可以调用run_forever(),然后运行我们的事件循环,直到调用stop()函数.

或者我们可以调用 run_until_complete(future) 并且只运行我们的事件循环,直到完成了我们传入的对象


The run_until_complete()方法:

我们快速浏览一下 run_until_complete()函数 ,在这个例子中,我们将定义myWork()协程,然后我们将其传递给run_until_complete函数,然后我们让我们的事件循环运行起来,直到完成 myWork() 协程的执行。

import asyncio
import time


async def my_work():
    print("开始执行任务")
    time.sleep(5)
    print("任务完成")

loop = asyncio.get_event_loop()
try:
    loop.run_until_complete(my_work())

finally:
    loop.close()
run_forever()方法:

启动事件循环的另一种方法是调用run_forever()方法,该方法随后将启动基于asyncio的事件循环,并使其无限期运行,直到程序结束或调用 stop() 方法。应该注意的是,调用它会导致我们的主线程无限期地阻塞。

我们来看一个快速示例,展示这种方法的用法。我们将首先定义我们的 work()协程,它将以无限期运行的while循环为特色,并以1秒的间隔打印出 Task 执行完成

import asyncio


async def work():
    while True:
        await asyncio.sleep(1)
        print("Task 执行完成")

loop = asyncio.get_event_loop()
try:
    asyncio.ensure_future(work())
    loop.run_forever()
except KeyboardInterrupt:
    pass
finally:
    print("关闭Loop")
    loop.close()
运行多个协程

如果你想无限期地并行运行多个协程,那么你可以通过创建x个协程并让它们分别运行while循环来实现。

然后调用 asyncio.ensure_future(function()) 将其添加在loop, 被加入的协程将在启动loop后无限期的运行。


import asyncio
import time


async def first_worker():
    while True:
        await asyncio.sleep(1)
        print("第一个任务完成")


async def second_worker():
    while True:
        await asyncio.sleep(1)
        print("第二个任务完成")


loop = asyncio.get_event_loop()
try:
    asyncio.ensure_future(first_worker())
    asyncio.ensure_future(second_worker())
    loop.run_forever()
except KeyboardInterrupt:
    pass
finally:
    print("关闭 Loop")
    loop.close()