Python 中的两个独立异步循环

Two independent async loops in Python

在 Python 中使用 async/await 并行执行两个异步循环 运行 的好方法是什么?

我考虑过类似下面代码的问题,但无法理解如何在这种特殊情况下使用 async/await/EventLoop

import asyncio

my_list = []

def notify():
    length = len(my_list)
    print("List has changed!", length)

async def append_task():
    while True:
        time.sleep(1)
        await my_list.append(random.random())
        notify()

async def pop_task():
    while True:
        time.sleep(1.8)
        await my_list.pop()
        notify()

loop = asyncio.get_event_loop()
loop.create_task(append_task())
loop.create_task(pop_task())
loop.run_forever()

预期输出:

$ python prog.py
List has changed! 1 # after 1sec
List has changed! 0 # after 1.8sec
List has changed! 1 # after 2sec
List has changed! 2 # after 3sec
List has changed! 1 # after 3.6sec
List has changed! 2 # after 4sec
List has changed! 3 # after 5sec
List has changed! 2 # after 5.4sec

这很好用:

注意:您想等待快速的非 io 绑定操作(list.appendlist.pop 甚至不是协程);你可以做的是 awaitasyncio.sleep(...) (这是一个协程并将控制权返回给调用者):

import asyncio
import random

my_list = []


def notify():
    length = len(my_list)
    print("List has changed!", length)

async def append_task():
    while True:
        await asyncio.sleep(1)
        my_list.append(random.random())
        notify()

async def pop_task():
    while True:
        await asyncio.sleep(1.8)
        my_list.pop()
        notify()


loop = asyncio.get_event_loop()
cors = asyncio.wait([append_task(), pop_task()])
loop.run_until_complete(cors)

time.sleep 本身是阻塞的,不能很好地与 await 一起玩。

列表对象没有可等待的操作,它们也不需要,因为没有 I/O 或您可以异步处理的其他延迟。

你也想用asyncio.sleep(),不是time.sleep();后者 .

以下工作正常;我在 notify 中添加了时间戳以更好地展示这一点:

from datetime import datetime
# ...

start = datetime.now()
def notify():
    length = len(my_list)
    print("t: {:.1f}, List has changed! {}".format(
        (datetime.now() - start).total_seconds(), length))

async def append_task():
    while True:
        await asyncio.sleep(1)
        my_list.append(random.random())
        notify()

async def pop_task():
    while True:
        await asyncio.sleep(1.8)
        my_list.pop()
        notify()

请注意,我们在 asyncio.sleep() 调用中使用 await;这提供了一个点,您的协程(cooperative 例程)将控制权交给另一个例程。

这会产生:

$ python asyncio_demo.py
t: 1.0, List has changed! 1
t: 1.8, List has changed! 0
t: 2.0, List has changed! 1
t: 3.0, List has changed! 2
t: 3.6, List has changed! 1
t: 4.0, List has changed! 2
t: 5.0, List has changed! 3
t: 5.4, List has changed! 2
t: 6.0, List has changed! 3