[英]how to add a coroutine to a running asyncio loop?
如何將新協程添加到正在運行的異步循環中? IE。 一個已經在執行一組協程的。
我想作為一種解決方法,可以等待現有協程完成,然后初始化一個新循環(使用額外的協程)。 但是有更好的方法嗎?
您可以使用create_task
來安排新的協程:
import asyncio
async def cor1():
...
async def cor2():
...
async def main(loop):
await asyncio.sleep(0)
t1 = loop.create_task(cor1())
await cor2()
await t1
loop = asyncio.get_event_loop()
loop.run_until_complete(main(loop))
loop.close()
要將函數添加到已經運行的事件循環中,您可以使用:
asyncio.ensure_future(my_coro())
在我的例子中,我使用多線程 ( threading
) 和asyncio
並想向已經運行的事件循環添加一個任務。 對於處於相同情況的其他任何人,請務必明確說明事件循環(因為Thread
中不存在事件循環)。 IE:
在全球范圍內:
event_loop = asyncio.get_event_loop()
然后,在你的Thread
中:
asyncio.ensure_future(my_coro(), loop=event_loop)
您的問題非常接近“How to add function call to running program?”
究竟什么時候需要向事件循環中添加新協程?
讓我們看一些例子。 這里程序用兩個協程並行啟動事件循環:
import asyncio
from random import randint
async def coro1():
res = randint(0,3)
await asyncio.sleep(res)
print('coro1 finished with output {}'.format(res))
return res
async def main():
await asyncio.gather(
coro1(),
coro1()
) # here we have two coroutines running parallely
if __name__ == "__main__":
loop = asyncio.get_event_loop()
loop.run_until_complete(main())
輸出:
coro1 finished with output 1
coro1 finished with output 2
[Finished in 2.2s]
可能您需要添加一些協程來獲取coro1
的結果並在准備就緒后立即使用它? 在那種情況下,只需創建等待coro1
的協程並使用它的返回值:
import asyncio
from random import randint
async def coro1():
res = randint(0,3)
await asyncio.sleep(res)
print('coro1 finished with output {}'.format(res))
return res
async def coro2():
res = await coro1()
res = res * res
await asyncio.sleep(res)
print('coro2 finished with output {}'.format(res))
return res
async def main():
await asyncio.gather(
coro2(),
coro2()
) # here we have two coroutines running parallely
if __name__ == "__main__":
loop = asyncio.get_event_loop()
loop.run_until_complete(main())
輸出:
coro1 finished with output 1
coro2 finished with output 1
coro1 finished with output 3
coro2 finished with output 9
[Finished in 12.2s]
將協同程序視為具有特定語法的常規函數。 您可以啟動一組函數來並行執行(通過asyncio.gather
),您可以在第一次完成后啟動下一個函數,您可以創建調用其他函數的新函數。
這里的答案似乎都不能准確回答問題。 通過讓“父”任務為您完成,可以將任務添加到正在運行的事件循環中。 我不確定什么是最 pythonic 的方式來確保父級在它的子級全部完成之前不會結束(假設這是你想要的行為),但這確實有效。
import asyncio
import random
async def add_event(n):
print('starting ' + str(n))
await asyncio.sleep(n)
print('ending ' + str(n))
return n
async def main(loop):
added_tasks = []
delays = list(range(5))
# shuffle to simulate unknown run times
random.shuffle(delays)
for n in delays:
print('adding ' + str(n))
task = loop.create_task(add_event(n))
added_tasks.append(task)
await asyncio.sleep(0)
print('done adding tasks')
results = await asyncio.gather(*added_tasks)
print('done running tasks')
return results
loop = asyncio.get_event_loop()
results = loop.run_until_complete(main(loop))
print(results)
如果任務是將協程添加到已經在執行某些協程的循環中,那么您可以使用我的這個解決方案
import asyncio
import time
from threading import Thread
from random import randint
# first, we need a loop running in a parallel Thread
class AsyncLoopThread(Thread):
def __init__(self):
super().__init__(daemon=True)
self.loop = asyncio.new_event_loop()
def run(self):
asyncio.set_event_loop(self.loop)
self.loop.run_forever()
# example coroutine
async def coroutine(num, sec):
await asyncio.sleep(sec)
print(f'Coro {num} has finished')
if __name__ == '__main__':
# init a loop in another Thread
loop_handler = AsyncLoopThread()
loop_handler.start()
# adding first 5 coros
for i in range(5):
print(f'Add Coro {i} to the loop')
asyncio.run_coroutine_threadsafe(coroutine(i, randint(3, 5)), loop_handler.loop)
time.sleep(3)
print('Adding 5 more coros')
# adding 5 more coros
for i in range(5, 10):
print(f'Add Coro {i} to the loop')
asyncio.run_coroutine_threadsafe(coroutine(i, randint(3, 5)), loop_handler.loop)
# let them all finish
time.sleep(60)
執行此示例后,我們將獲得以下輸出:
Add Coro 0 to the loop
Add Coro 1 to the loop
Add Coro 2 to the loop
Add Coro 3 to the loop
Add Coro 4 to the loop
Coro 0 has finished
Adding 5 more coros
Add Coro 5 to the loop
Add Coro 6 to the loop
Add Coro 7 to the loop
Add Coro 8 to the loop
Add Coro 9 to the loop
Coro 1 has finished
Coro 3 has finished
Coro 2 has finished
Coro 4 has finished
Coro 9 has finished
Coro 5 has finished
Coro 7 has finished
Coro 6 has finished
Coro 8 has finished
Process finished with exit code 0
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.