gpt4 book ai didi

python - 未等待的任务总是在通过 create_task 创建时开始吗?

转载 作者:行者123 更新时间:2023-11-28 17:57:00 25 4
gpt4 key购买 nike

我正在尝试创建服务器,但我很难理解如何使用 create_task 启动协程。在第一个测试中,create_task 似乎立即启动任务。但是在第二个测试中,它似乎直到等待它才开始。

import asyncio

async def task_test():
async def delayed_print(delay, message):
await asyncio.sleep(delay)
print(message)

print_task = asyncio.create_task(delayed_print(2, "Hello"))
await asyncio.sleep(5)
print("World")
await print_task

asyncio.run(task_test())
Hello
World

如果 print_task 仅在到达 await print_task 时才开始,则将打印“World\nHello”。


问题是,这似乎与我在 AbstractServerserve_forever 函数中看到的行为相矛盾。如果我为启动服务器设置类似的测试:

async def server_test():
server: asyncio.AbstractServer = await asyncio.start_server(lambda r, w: print("conn"), "127.0.0.1", 5555)

serve_task = asyncio.create_task(server.serve_forever())

# await serve_task # The pivotal part
return server

服务器仅在(当前注释的)await 行执行时接受传入连接;建议 serve_forever 需要 awaiting 才能正常工作。

证据:

asyncio.run(server_test())  # With "await serve_task" commented out
# Returns

# --- In another REPL

rdr, wtr = asyncio.run(asyncio.open_connection("127.0.0.1", 5555))
Traceback (most recent call last):
# Truncated - It's very long
raise OSError(err, f'Connect call failed {address}')
ConnectionRefusedError: [Errno 10061] Connect call failed ('127.0.0.1', 5555)

由于客户端无法连接到服务器而出错。

如果我取消注释该行:

asyncio.run(server_test())  # With "await serve_task" executing
# Never returns

# --- In another REPL

rdr, wtr = asyncio.run(asyncio.open_connection("127.0.0.1", 5555))

(rdr, wtr)
(<StreamReader transport=<_SelectorSocketTransport fd=1064>>, <StreamWriter transport=<_SelectorSocketTransport fd=1064> reader=<StreamReader transport=<_SelectorSocketTransport fd=1064>>>)

它连接成功(“conn”在服务器 REPL 中打印出来)。

谁能解释为什么 serve_forever 只允许服务器在等待时接受连接?我宁愿不需要显式地 await serve_task。为什么?:

  • 我想了解为什么这两个非常相似的代码之间存在差异,这样我就可以避免 future 的陷阱,但主要是......

  • 因为我不想await serve_forever。这将创建一个有效的无限阻塞调用,阻止服务器执行任何新操作。理想情况下,我希望能够在 REPL 中启动服务器,并向本地服务器发送命令以执行操作。按照现在的情况,只要我启动服务器,REPL 就会被阻塞。我想出的唯一解决方法是预先创建我要运行的任务并延迟它们,然后将它们和 serve_forever 交给 gather。像这样的东西:

    asyncio.gather(server.serve_forever(),
    some_delayed_task,
    some_other_delayed_task)

此处的任何清晰度将不胜感激。

最佳答案

您不必等待 create_task(serve_forever()) 的结果。但是,您确实需要await something。在asyncio中,一次只能发生一件事,并且只能通过await在任务之间切换。在您到达 await 之前,serve_forever 任务实际上并未运行。

您在 REPL 中看到的问题是因为 REPL 不是根据 asyncio 实现的,所以当您坐在 repl 提示符下时没有 asyncio 可以运行任务。尝试使用 aioconsole而不是标准的 REPL。

关于python - 未等待的任务总是在通过 create_task 创建时开始吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57734313/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com