如何正确使用asyncio run_coroutine_threadsafe函数?

Art*_*rev 8 python multithreading asynchronous python-3.x python-asyncio

我试图理解 asyncio 模块并花了大约一小时使用 run_coroutine_threadsafe 函数,我什至来到了工作示例,它按预期工作,但有一些限制。

首先,我不明白应该如何在主(任何其他)线程中正确调用 asyncio 循环,在示例中我调用它并run_until_complete给它一个协程以使其忙于某些事情,直到另一个线程不会给它一个协程。我还有什么其他选择?

在现实生活中,什么情况下我必须混合使用异步和线程(在 Python 中)?据我了解,asyncio 应该取代 Python 中的线程(由于 GIL 不是 IO 操作),如果我错了,请不要生气并分享您的建议。

Python版本为3.7/3.8

import asyncio
import threading
import time


async def coro_func():
    return await asyncio.sleep(3, 42)


def another_thread(_loop):
    coro = coro_func()  # is local thread coroutine which we would like to run in another thread

    # _loop is a loop which was created in another thread

    future = asyncio.run_coroutine_threadsafe(coro, _loop)
    print(f"{threading.current_thread().name}: {future.result()}")
    time.sleep(15)
    print(f"{threading.current_thread().name} is Finished")


if __name__ == '__main__':
    loop = asyncio.get_event_loop()
    main_th_cor = asyncio.sleep(10)
    # main_th_cor  is used to make loop busy with something until another_thread will not send coroutine to it
    print("START MAIN")
    x = threading.Thread(target=another_thread, args=(loop, ), name="Some_Thread")
    x.start()
    time.sleep(1)
    loop.run_until_complete(main_th_cor)
    print("FINISH MAIN")

Run Code Online (Sandbox Code Playgroud)

use*_*342 7

首先,我不明白应该如何在主(任何其他)线程中正确调用 asyncio 循环,在示例中我调用它并run_until_complete给它一个协程以使其忙于某些事情,直到另一个线程不会给它一个协程。我还有什么其他选择?

这是一个很好的用例loop.run_forever()。该循环将运行并为您使用 提交的协程提供服务run_coroutine_threadsafe。(您甚至可以从多个线程并行提交此类协程;您永远不需要实例化多个事件循环。)

您可以通过调用从不同线程停止循环loop.call_soon_threadsafe(loop.stop)

在现实生活中,什么情况下我必须混合使用异步和线程(在 Python 中)?

理想情况下应该没有。但在现实世界中,它们确实会突然出现。例如:

  • 当您将 asyncio 引入到使用线程和阻塞调用且无法一次性全部转换为 asyncio 的现有大型程序时。run_coroutine_threadsafe允许常规阻塞代码使用 asyncio。

  • 当您处理较旧的“异步”API 时,这些 API 在幕后使用线程并从其他线程调用用户提供的 API。例子有很多,比如Python自己的multiprocessing.

  • 当您需要调用与 asyncio 没有异步等效项的阻塞函数时 - 例如 CPU 绑定函数、遗留数据库驱动程序等。这不是 的用例run_coroutine_threadsafe,这里您将使用run_in_executor,但它是混合线程和 asyncio 的另一个示例。