让 asyncio 按顺序运行函数(Python 3)
Posted
技术标签:
【中文标题】让 asyncio 按顺序运行函数(Python 3)【英文标题】:Getting asyncio to run a function in order (Python 3) 【发布时间】:2018-04-24 14:15:09 【问题描述】:这是一个使用asyncio
打印从0 到9 的数字的简单示例。
问题:有时代码会打印出从 0 到 7 的数字,然后打印 9,然后是 8。尤其是当您将 ThreadPoolExecutor
设置为较小的数字(例如 4 或 5)时。
0
1
2
3
4
5
6
7
9
8
你如何让它总是按从 0 到 9 的顺序打印?为什么没有按顺序打印?
0
1
2
3
4
5
6
7
8
9
代码
import asyncio
from concurrent.futures import ThreadPoolExecutor
async def printThreaded(THREAD_POOL, length):
loop = asyncio.get_event_loop()
futures = []
for i in range(length):
futures.append(loop.run_in_executor(THREAD_POOL, echo, i))
await asyncio.wait(futures)
def echo(i):
print(i)
THREAD_POOL = ThreadPoolExecutor(16)
with THREAD_POOL:
loop = asyncio.get_event_loop()
length = 10
loop.run_until_complete(printThreaded(THREAD_POOL, length))
【问题讨论】:
Possible duplicate? 【参考方案1】:你的代码现在发生了什么?
您创建的协程列表 (futures
) 将在线程池中运行 echo
,而不是一次启动它们 (await asyncio.wait(futures)
)。由于多个echo
同时运行并且每个打印都在运行,所有这些打印都可以随时发生。
你想做什么?
你可能真的不想按顺序运行协程(否则你可以在没有asyncio
的情况下循环调用它),你想在线程池中同时运行它们,但是按协程的顺序打印它们的结果已创建
在这种情况下,您应该:
将线程中发生的实际工作从 打印出来
可能更喜欢使用asyncio.gather来按顺序获取计算结果
最后打印你在主线程中得到的有序结果
总结
这是上面解释过的代码的修改版本:
import time
from random import randint
import asyncio
from concurrent.futures import ThreadPoolExecutor
async def printThreaded(THREAD_POOL, length):
loop = asyncio.get_event_loop()
# compute concurrently:
coroutines = []
for i in range(length):
coroutine = loop.run_in_executor(THREAD_POOL, get_result, i)
coroutines.append(coroutine)
results = await asyncio.gather(*coroutines)
# print ordered results:
for res in results:
print(res)
def get_result(i):
time.sleep(randint(0, 2)) # actual work, reason you delegate 'get_result' function to threaed
return i # compute and return, but not print yet
THREAD_POOL = ThreadPoolExecutor(4)
with THREAD_POOL:
loop = asyncio.get_event_loop()
length = 10
loop.run_until_complete(printThreaded(THREAD_POOL, length))
【讨论】:
以上是关于让 asyncio 按顺序运行函数(Python 3)的主要内容,如果未能解决你的问题,请参考以下文章
Python - 在 asyncio 中运行函数的正确方法是啥?
如何使用 python 的 asyncio 模块正确创建和运行并发任务?