Python 如何将协程添加到正在运行的 asyncio 循环中?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/34499400/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
how to add a coroutine to a running asyncio loop?
提问by Petri
How can one add a new coroutine to a running asyncio loop? Ie. one that is already executing a set of coroutines.
如何向正在运行的 asyncio 循环添加新的协程?IE。一个已经在执行一组协程的。
I guess as a workaround one could wait for existing coroutines to complete and then initialize a new loop (with the additional coroutine). But is there a better way?
我想作为一种解决方法,可以等待现有协程完成,然后初始化一个新循环(使用额外的协程)。但是有更好的方法吗?
采纳答案by Jashandeep Sohi
You can use create_task
for scheduling new coroutines:
您可以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()
回答by Mikhail Gerasimov
Your question is very close to "How to add function call to running program?"
您的问题非常接近“如何向正在运行的程序添加函数调用?”
When exactly you need to add new coroutine to event loop?
什么时候需要向事件循环添加新的协程?
Let's see some examples. Here program that starts event loop with two coroutines parallely:
让我们看一些例子。这里程序用两个协程并行启动事件循环:
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())
Output:
输出:
coro1 finished with output 1
coro1 finished with output 2
[Finished in 2.2s]
May be you need to add some coroutines that would take results of coro1
and use it as soon as it's ready? In that case just create coroutine that await coro1
and use it's returning value:
您可能需要添加一些协程,这些协程会在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())
Output:
输出:
coro1 finished with output 1
coro2 finished with output 1
coro1 finished with output 3
coro2 finished with output 9
[Finished in 12.2s]
Think about coroutines as about regular functions with specific syntax. You can start some set of functions to execute parallely (by asyncio.gather
), you can start next function after first done, you can create new functions that call others.
将协程视为具有特定语法的常规函数。您可以启动一组函数并行执行(by asyncio.gather
),您可以在第一次完成后启动下一个函数,您可以创建调用其他函数的新函数。
回答by Dotl
To add a function to an already running event loop you can use:
要将函数添加到已经运行的事件循环中,您可以使用:
asyncio.ensure_future(my_coro())
asyncio.ensure_future(my_coro())
In my case I was using multithreading (threading
) alongside asyncio
and wanted to add a task to the event loop that was already running. For anyone else in the same situation, be sure to explicitly state the event loop (as one doesn't exist inside a Thread
). i.e:
在我的例子中,我同时使用了多线程 ( threading
)asyncio
并想向已经运行的事件循环添加一个任务。对于处于相同情况的其他任何人,请务必明确说明事件循环(因为 a 中不存在Thread
)。IE:
In global scope:
在全球范围内:
event_loop = asyncio.get_event_loop()
Then later, inside your Thread
:
然后,在您的内部Thread
:
asyncio.ensure_future(my_coro(), loop=event_loop)
回答by Adam
None of the answers here seem to exactly answer the question. It is possible to add tasks to a running event loop by having a "parent" task do it for you. I'm not sure what the most pythonic way to make sure that parent doesn't end until it's children have all finished (assuming that's the behavior you want), but this does work.
这里的答案似乎都没有完全回答这个问题。通过让“父”任务为您执行,可以将任务添加到正在运行的事件循环中。我不确定确保父母在孩子都完成之前不会结束的最 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 = [x for x in 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)