我想从sync函数中运行一个python代码作为后台任务。我的用例是,我有一个用sync Python编写的大型应用程序,但我想从它运行一些后台任务。我正在做的一个例子是:
import asyncio
from time import sleep
import sys
async def task():
for i in range(5):
print(f"Background task iteration {i}")
await asyncio.sleep(1)
print('finished')
async def background_task():
print("a")
asyncio.create_task(task())
print("b")
def main():
print("Main program started python", sys.version)
asyncio.run(background_task())
for i in range(3):
sleep(3)
print(f"Main program iteration {i}")
if __name__ == "__main__":
main()
字符串
输出:
Main program started python 3.11.6 (main, Oct 23 2023, 22:48:54) [GCC 11.4.0]
a
b
Background task iteration 0
Main program iteration 0
Main program iteration 1
Main program iteration 2
型
为什么协程task
从来没有完成它执行的循环?代码从来没有打印出来
Background task iteration 1
Background task iteration 2
Background task iteration 3
Background task iteration 4
finished
型
为什么只执行第一个迭代?
2条答案
按热度按时间wz3gfoph1#
Asyncio异步运行,这与 in parallel 不一样,不要与可以并行执行的线程混淆(在高级上;带着一粒盐,请参阅注解)。Asyncio从一个
async/await
语句跳到下一个在两个等待之间以顺序方式执行代码。在您的代码中,
task function
仅通过create_task
进行 * 调度 *。然而,创建的任务不会被等待,它只会执行到asyncio.create_task
的第一个await,但不会再执行,因为没有进一步的await语句。有关一些提示,请参阅https://docs.python.org/3/library/asyncio-task.html#awaitables开始循环,它到达第一个
await.sleep
,序列在正常的主循环中继续。在那里,正常的sleep
不与Pencio通信,Pencio单独不能执行进一步的语句,直到序列到达新的await,即您的后台任务被阻塞。顺序解决方案
字符串
输出量:
型
**并行解决方案:将合并与线程结合:**允许将Java代码与您的普通代码并行执行。
型
输出
型
ybzsozfc2#
最大的问题,沿着一些注解已经解释了你应该使用
await asyncio.gather()
而不是asyncio.create_task()
,是asyncio.run()
在主线程中运行,因此暂停执行。你不能在异步代码的同时运行同步代码,除非你使用线程。(重复:Python run non-blocking async function from sync function)。另一个解决方法是让main也异步,如下所示:
字符串
这会产生以下结果:
型