简体   繁体   English

如何正确使用 asyncio run_coroutine_threadsafe 函数?

[英]How to properly use asyncio run_coroutine_threadsafe function?

I am trying to understand asyncio module and spend about one hour with run_coroutine_threadsafe function, I even came to the working example, it works as expected, but works with several limitations.我正在尝试理解 asyncio 模块并花了大约一个小时的时间使用 run_coroutine_threadsafe 函数,我什至来到了工作示例,它按预期工作,但有几个限制。

First of all I do not understand how should I properly call asyncio loop in main (any other) thread, in the example I call it with run_until_complete and give it a coroutine to make it busy with something until another thread will not give it a coroutine.首先,我不明白我应该如何在主(任何其他)线程中正确调用 asyncio 循环,在示例中我用run_until_complete调用它并给它一个协程使其忙于某事,直到另一个线程不会给它一个协程. What are other options I have?我还有哪些其他选择?

What are situations when I have to mix asyncio and threading (in Python) in real life?在现实生活中我必须混合异步和线程(在 Python 中)的情况是什么? Since as far as I understand asyncio is supposed to take place of threading in Python (due to GIL for not IO ops), if I am wrong, do not be angry and share your suggestions.由于据我所知 asyncio 应该取代 Python 中的线程(由于 GIL 不是 IO 操作),如果我错了,请不要生气并分享您的建议。

Python version is 3.7/3.8 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")

First of all I do not understand how should I properly call asyncio loop in main (any other) thread, in the example I call it with run_until_complete and give it a coroutine to make it busy with something until another thread will not give it a coroutine.首先,我不明白我应该如何在主(任何其他)线程中正确调用 asyncio 循环,在示例中我用run_until_complete调用它并给它一个协程使其忙于某事,直到另一个线程不会给它一个协程. What are other options I have?我还有哪些其他选择?

This is a good use case for loop.run_forever() .这是loop.run_forever()一个很好的用例。 The loop will run and serve the coroutines you submit using run_coroutine_threadsafe .该循环将运行并为您使用run_coroutine_threadsafe提交的协程提供服务。 (You can even submit such coroutines from multiple threads in parallel; you never need to instantiate more than one event loop.) (你甚至可以从多个线程并行提交这样的协程;你永远不需要实例化一个以上的事件循环。)

You can stop the loop from a different thread by calling loop.call_soon_threadsafe(loop.stop) .您可以通过调用loop.call_soon_threadsafe(loop.stop)从不同的线程停止循环。

What are situations when I have to mix asyncio and threading (in Python) in real life?在现实生活中我必须混合异步和线程(在 Python 中)的情况是什么?

Ideally there should be none.理想情况下应该没有。 But in the real world, they do crop up;但在现实世界中,它们确实会出现。 for example:例如:

  • When you are introducing asyncio into an existing large program that uses threads and blocking calls and cannot be converted to asyncio all at once.当您将 asyncio 引入现有的大型程序时,该程序使用线程和阻塞调用并且不能一次全部转换为 asyncio。 run_coroutine_threadsafe allows regular blocking code to make use of asyncio. run_coroutine_threadsafe允许常规阻塞代码使用 asyncio。

  • When you are dealing with older "async" APIs which use threads under the hood and call the user-supplied APIs from other threads.当您处理旧的“异步”API 时,这些 API 在后台使用线程并从其他线程调用用户提供的 API。 There are many examples, such as Python's own multiprocessing .有很多例子,比如 Python 自带的multiprocessing

  • When you need to call blocking functions that have no async equivalent from asyncio - eg CPU-bound functions, legacy database drivers, things like that.当您需要从 asyncio 调用没有异步等效项的阻塞函数时 - 例如 CPU 绑定函数、遗留数据库驱动程序等。 This is not a use case for run_coroutine_threadsafe , here you'd use run_in_executor , but it is another example of mixing threads and asyncio.这不是run_coroutine_threadsafe的用例,在这里您将使用run_in_executor ,但它是混合线程和 asyncio 的另一个示例。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM