gpt4 book ai didi

python - 如何在不使用await的情况下拆分长协程?

转载 作者:行者123 更新时间:2023-12-01 01:48:40 31 4
gpt4 key购买 nike

我有一个协程变得太大,我想将其拆分以提高可读性。

async def handle_message(self, message):
message_type = message.get('type')

if message_type == 'broadcast':
...
for n in self._neighbors:
await self.send_message(n, message)

elif message_type == 'graph':
...

我想将处理广播消息的部分提取到一个私有(private)方法中,如下所示:

async def handle_message(self, message):
message_type = message.get('type')
...

if message_type = 'broadcast':
await self._handle_broadcast(message)
elif message_type = 'graph':
...

问题在于,这会改变代码的行为,因为 _handle_broadcast 部分是一个协程,并且由于我使用 await 调用它,因此它的执行可能会延迟。

如何保证协程立即运行且不延迟?

最佳答案

简而言之:就像开始时一样,使用 await 来拆分协程。 .

The problem is that this changes the behavior of the code, since the _handle_broadcast part is a coroutine and its execution might be delayed since I call it with await.

无论好坏,这个前提都是错误的。当给定一个协程时,await立即开始执行,没有中间延迟。只有如果协程调用了导致其挂起的内容(例如 asyncio.sleep 或尚未有数据的网络读取),您的协程就会随之挂起 - 这正是如果代码保持内联,您会得到什么。

从这个意义上说await <some coroutine>其工作方式类似于常规函数调用的协程,精确地允许您需要的那种不改变语义的重构。这可以用一个例子来证明:

import asyncio

async def heartbeat():
while True:
print('tick')
await asyncio.sleep(1)

async def noop():
pass

async def coro():
# despite "await", this blocks the event loop!
while True:
await noop()

loop = asyncio.get_event_loop()
loop.create_task(heartbeat())
loop.create_task(coro())
loop.run_forever()

上面的代码阻止了事件循环 - 即使 coro除了 await 之外什么都不做循环中。所以await并不能保证屈服于事件循环,协程必须通过其他方式来完成。 (此行为也可能是 bugs 的来源。)

在上述情况下,可以通过插入 await asyncio.sleep(0) 来使事件循环“解除卡住”。 。但在生产异步代码中永远不需要这种东西,程序的结构应该使每个协程只做相对较少的工作,然后使用 await以获得更多数据。

关于python - 如何在不使用await的情况下拆分长协程?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50954850/

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