gpt4 book ai didi

Python create_task 在运行事件循环中不起作用

转载 作者:太空宇宙 更新时间:2023-11-04 09:29:08 25 4
gpt4 key购买 nike

我有一段简单的代码让我发疯了一段时间。我已经发布了this几天前询问 create_task 的问题不适用于 input。现在我想出了与此相关的事情。我在一个单独的线程中运行事件循环并在其中推送任务。非常直接的代码。

import asyncio
import threading


async def printer(message):
print(f'[printer] {message}')


def loop_runner(loop):
loop.run_forever()


if __name__ == '__main__':
event_loop = asyncio.get_event_loop()
t = threading.Thread(target=loop_runner, args=(event_loop,))
t.start()

for m in ['hello', 'world', 'foo', 'bar']:
print(f'[loop running ?] {event_loop.is_running()}')
event_loop.create_task(printer(m))

除了这些日志消息之外,没有任何内容被打印出来。

[loop running ?] True
[loop running ?] True
[loop running ?] True
[loop running ?] True

现在,如果我阻塞事件循环线程并让它在这样的暂停后运行。

def loop_runner(loop):
time.sleep(1 / 1000)
loop.run_forever()

一切正常,打印出来

[loop running ?] False
[loop running ?] False
[loop running ?] False
[loop running ?] False
[printer] hello
[printer] world
[printer] foo
[printer] bar

从表面上看,在运行事件循环中创建的任务似乎没有得到执行。但这是为什么呢?

我没有在文档中看到任何关于此的信息。在我在互联网上看到的大多数示例中,人们正在从其他协程循环创建任务并等待它们。但我认为如果您不想等待它们,在协程之外使用创建任务是合法的。

最佳答案

从事件循环线程外创建任务时,需要使用asyncio.run_coroutine_threadsafe .该函数将以线程安全的方式安排协程,并通知事件循环有新的工作要做。它还将返回 concurrent.futures.Future对象,您可以使用它来阻塞当前线程,直到结果可用。

From surface it looks like tasks created in running event loop do not get executed. But why is that?

调用 create_task是不够的,因为它不包含“唤醒”事件循环的代码。这是一个特性——通常不需要这样的唤醒,添加它只会减慢常规的单线程使用。当从事件循环线程调用 create_task 时,它在事件循环回调中,因此事件循环可以在它重新获得控制权后立即检查其任务队列,当它完成回调时。但是当 create_task 从不同的线程调用时,事件循环正在等待 IO,因此需要 run_coroutine_threadsafe 将其唤醒。

要对此进行测试,您可以创建一个“心跳”协程,它只包含一个打印内容并等待 asyncio.sleep(1) 的无限循环。您会看到使用 create_task 创建的任务会随着心跳一起执行,这也恰好会唤醒事件循环。在繁忙的 asyncio 应用程序中,这种效果给人的印象是来自另一个线程的 create_task “有效”。但是,永远不要依赖它,因为 create_task 无法实现正确的锁定并且可能会破坏事件循环内部结构。

I have not seen anything regarding this in documentation.

看看 concurrency and multithreading部分。

关于Python create_task 在运行事件循环中不起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56385876/

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