检查 asyncio.get_event_loop() 是否完成?
Check if asyncio.get_event_loop() has finished?
我有一个自定义背景装饰器。当我在后台 运行 一个函数时,我如何检查我在后台启动的所有函数是否都已完成,直到我 return?
#background decorator
def background(fn):
def wrapped(*args, **kwargs):
return asyncio.get_event_loop().run_in_executor(None, fn, *args, **kwargs)
return wrapped
#myfunction that I run in the background
@background
def myfunction():
#run some tasks
#main here I call "myfunction"
def main():
for i in list:
myfunction()
#check if all myfunction's are done then return (MY PROBLEM)
在你的主函数之外,你应该定义你的循环,并使用它来等待所有将 运行 在你的主函数中的函数,直到它们完成:
loop = asyncio.new_event_loop()
asyncio.set_event_loop(loop)
loop.run_until_complete(main()) # <- This is what you are looking for
loop.close()
然后,在你的包装函数中使用这样的循环:
await loop.run_in_executor(...)
并记住在适当的地方使用 async
和 await
表达式。
您可以列出 myfunction() 任务,然后使用 asyncio.wait()
运行 它们
import asyncio
from timeit import default_timer as timer
def background(fn):
def wrapped(*args, **kwargs):
return asyncio.get_event_loop().run_in_executor(None, fn, *args,**kwargs)
return wrapped
@background
def myfunction(tasknum):
print("tasknum",tasknum," -- started at", timer())
#add lots of numbers to simulate some task...
x = 0
for n in range(20000000):
x += n
print("tasknum",tasknum," -- finished at", timer())
def main():
print("main -- started at", timer())
background_loop = asyncio.get_event_loop()
tasks = []
for i in range(4):
tasks.append(myfunction(i))
try:
background_loop.run_until_complete(asyncio.wait(tasks))
finally:
background_loop.close()
print("main -- finished at", timer())
main()
print('returned from main')
输出:
main -- started at 38203.24129425
tasknum 0 -- started at 38203.241935683
tasknum 1 -- started at 38203.24716722
tasknum 2 -- started at 38203.257414232
tasknum 3 -- started at 38203.257518981
tasknum 1 -- finished at 38206.503383425
tasknum 2 -- finished at 38206.930789807
tasknum 0 -- finished at 38207.636296604
tasknum 3 -- finished at 38207.833483453
main -- finished at 38207.833736195
returned from main
注意 get_event_loop() 在 python 3.10 中被弃用,所以最好的解决方案可能是在装饰器定义之前启动后台循环,然后直接使用循环名称:
background_loop = asyncio.new_event_loop()
def background(fn):
def wrapped(*args, **kwargs):
return background_loop.run_in_executor(None, fn, *args, **kwargs)
return wrapped
我有一个自定义背景装饰器。当我在后台 运行 一个函数时,我如何检查我在后台启动的所有函数是否都已完成,直到我 return?
#background decorator
def background(fn):
def wrapped(*args, **kwargs):
return asyncio.get_event_loop().run_in_executor(None, fn, *args, **kwargs)
return wrapped
#myfunction that I run in the background
@background
def myfunction():
#run some tasks
#main here I call "myfunction"
def main():
for i in list:
myfunction()
#check if all myfunction's are done then return (MY PROBLEM)
在你的主函数之外,你应该定义你的循环,并使用它来等待所有将 运行 在你的主函数中的函数,直到它们完成:
loop = asyncio.new_event_loop()
asyncio.set_event_loop(loop)
loop.run_until_complete(main()) # <- This is what you are looking for
loop.close()
然后,在你的包装函数中使用这样的循环:
await loop.run_in_executor(...)
并记住在适当的地方使用 async
和 await
表达式。
您可以列出 myfunction() 任务,然后使用 asyncio.wait()
运行 它们import asyncio
from timeit import default_timer as timer
def background(fn):
def wrapped(*args, **kwargs):
return asyncio.get_event_loop().run_in_executor(None, fn, *args,**kwargs)
return wrapped
@background
def myfunction(tasknum):
print("tasknum",tasknum," -- started at", timer())
#add lots of numbers to simulate some task...
x = 0
for n in range(20000000):
x += n
print("tasknum",tasknum," -- finished at", timer())
def main():
print("main -- started at", timer())
background_loop = asyncio.get_event_loop()
tasks = []
for i in range(4):
tasks.append(myfunction(i))
try:
background_loop.run_until_complete(asyncio.wait(tasks))
finally:
background_loop.close()
print("main -- finished at", timer())
main()
print('returned from main')
输出:
main -- started at 38203.24129425
tasknum 0 -- started at 38203.241935683
tasknum 1 -- started at 38203.24716722
tasknum 2 -- started at 38203.257414232
tasknum 3 -- started at 38203.257518981
tasknum 1 -- finished at 38206.503383425
tasknum 2 -- finished at 38206.930789807
tasknum 0 -- finished at 38207.636296604
tasknum 3 -- finished at 38207.833483453
main -- finished at 38207.833736195
returned from main
注意 get_event_loop() 在 python 3.10 中被弃用,所以最好的解决方案可能是在装饰器定义之前启动后台循环,然后直接使用循环名称:
background_loop = asyncio.new_event_loop()
def background(fn):
def wrapped(*args, **kwargs):
return background_loop.run_in_executor(None, fn, *args, **kwargs)
return wrapped