事件循环上计划的任务的执行顺序 (Python 3.10)

发布于 2025-01-15 06:25:14 字数 1304 浏览 2 评论 0原文

我仍在学习 python 3.10 中的 asyncio 模块。下面是我编写的代码,试图了解如何在事件循环上将协程作为任务运行。我得到的输出与我的预期不同。请帮助我理解我做错了什么或者是否有什么我误解的地方。

import asyncio 
    async def f(x):
        try:
            print(f"Inside f({x})...")
            await asyncio.sleep(x)
            print(f'slept for {x} seconds!!')
            return x
        except asyncio.CancelledError:  # Execute this part only when the task is cancelled.
            print(f'Cancelled({x})')
    
    async def main():
        loop = asyncio.get_running_loop()
    
        task1 = loop.create_task(f(1), name="task1")
        task2 = loop.create_task(f(2), name="task2")
        task3 = loop.create_task(f(3), name="task3")
    
        print(task1.done())
        print(task2.done())
        print(task3.done())
    
    asyncio.run(main())

输出:

False False False 在 f(1) 内... 在 f(2) 内... 在 f(3) 内... 已取消(3) 已取消(1) 已取消(2)

我希望此代码在 print(task3.done()) 之后立即退出 main() ,并且仅运行协程函数 f 的异常处理部分(x),但事件循环在实际退出之前恰好运行 f(1)、f(2) 和 f(3) 的功能一次。 我的疑问是

  1. 为什么事件循环上的所有任务在取消之前都会运行一次?
  2. 执行顺序是什么(如果有的话,是固定的还是随机的?)

编辑: 我首先尝试使用 task1 = asyncio.create_task(f(1), name = "task1")。然后我使用了loop.create_task()。两者都给出相同的输出(我猜这是预期的)。

I am still learning the asyncio module in python 3.10. Below is a code I wrote trying to understand how to run coroutines as tasks on an event loop. the output I am getting is different from what I expected. Please help me understand what I am doing wrong or if there is something I misunderstood.

import asyncio 
    async def f(x):
        try:
            print(f"Inside f({x})...")
            await asyncio.sleep(x)
            print(f'slept for {x} seconds!!')
            return x
        except asyncio.CancelledError:  # Execute this part only when the task is cancelled.
            print(f'Cancelled({x})')
    
    async def main():
        loop = asyncio.get_running_loop()
    
        task1 = loop.create_task(f(1), name="task1")
        task2 = loop.create_task(f(2), name="task2")
        task3 = loop.create_task(f(3), name="task3")
    
        print(task1.done())
        print(task2.done())
        print(task3.done())
    
    asyncio.run(main())

Output:

False False False Inside f(1)... Inside f(2)... Inside f(3)...
Cancelled(3) Cancelled(1) Cancelled(2)

I expect this code to exit main() immediately after print(task3.done()) and only run the exception handling part of the coroutine function f(x), but the event loop runs the functionalities of f(1), f(2) and f(3) exactly one time before actually exiting.
My doubts are

  1. Why do all the tasks on the event loop run once before getting cancelled?
  2. What is the execution order (if there is any, is it fixed or random?)

Edit:
I first tried using task1 = asyncio.create_task(f(1), name = "task1"). Then I used loop.create_task(). Both give same output(which is to be expected I guess).

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

旧街凉风 2025-01-22 06:25:14

我认为你应该将“task1 = loop.create_task(f(1), name="task1")”行更改为“task1 = asyncio.create_task(f(1), name="task1")”

I think you should change the line "task1 = loop.create_task(f(1), name="task1")" to be "task1 = asyncio.create_task(f(1), name="task1")"

檐上三寸雪 2025-01-22 06:25:14

您的程序在异步任务完成之前就已完成,因此它们都将被取消。对 done() 的调用只是打印出它们还没有完成。

如果您想让任务有机会完成,除了前面的答案之外,您还需要添加 await(task1) 等。或者只是
await asyncio.gather(task1, task2, task3) 在一次调用中等待所有这些任务。

Your program is finishing before your asynchronous tasks are done, so they are all being cancelled. The call to done() just prints that they're not done.

You need to add await(task1), etc. in addition to the previous answer if you want to give your tasks the chance to finish. Or just
await asyncio.gather(task1, task2, task3) to wait for all of them in one call.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文