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.append
和 list.pop
甚至不是协程);你可以做的是 await
asyncio.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
在 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.append
和 list.pop
甚至不是协程);你可以做的是 await
asyncio.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