如何在 Python 中为线程设置异步事件循环? [英] How do I set the asyncio event loop for a thread in Python?
问题描述
我正在尝试创建两个线程,每个线程都有自己的异步事件循环.
I'm trying to create two threads that each have their own asyncio event loop.
我尝试了以下代码,但似乎不起作用:
I've tried the following code but it doesn't seem to work:
import asyncio
from threading import Thread
def hello(thread_name):
print('hello from thread {}!'.format(thread_name))
event_loop_a = asyncio.new_event_loop()
event_loop_b = asyncio.new_event_loop()
def callback_a():
asyncio.set_event_loop(event_loop_a)
asyncio.get_event_loop().call_soon_threadsafe(lambda: hello('a'))
def callback_b():
asyncio.set_event_loop(event_loop_b)
asyncio.get_event_loop().call_soon_threadsafe(lambda: hello('b'))
thread_a = Thread(target=callback_a, daemon=True)
thread_b = Thread(target=callback_b, daemon=True)
thread_a.start()
thread_b.start()
我的用例是调用 Tornado Web 框架的 websocket_connect 异步函数.
My use case is calling Tornado web framework's websocket_connect async function.
推荐答案
您的线程正在它们各自的事件循环中排队回调,但它们在实际运行事件循环之前退出,因此回调永远不会得到执行.此外,您不需要 call_soon_threadsafe代码>
,因为您是从同一线程调用回调,事件循环正在(或者更确切地说,将)运行.
Your threads are queuing callbacks in their respective event loops, but they exit before actually running the event loop, so the callbacks never get executed. Also, you don't need call_soon_threadsafe
, since you are invoking the callback from the same thread the event loop is (or, rather, will be) running on.
此代码打印预期的输出:
This code prints the expected output:
import asyncio
from threading import Thread
def hello(thread_name):
print('hello from thread {}!'.format(thread_name))
event_loop_a = asyncio.new_event_loop()
event_loop_b = asyncio.new_event_loop()
def callback_a():
asyncio.set_event_loop(event_loop_a)
asyncio.get_event_loop().call_soon(lambda: hello('a'))
event_loop_a.run_forever()
def callback_b():
asyncio.set_event_loop(event_loop_b)
asyncio.get_event_loop().call_soon(lambda: hello('b'))
event_loop_b.run_forever()
thread_a = Thread(target=callback_a, daemon=True)
thread_b = Thread(target=callback_b, daemon=True)
thread_a.start()
thread_b.start()
call_soon_threadsafe
的一个更典型的用例,并且更符合您的想法,是提交回调(或使用 asyncio.run_coroutine_threadsafe
) 到另一个线程中运行的事件循环.下面是一个例子:
A more typical use case for call_soon_threadsafe
, and more in line with what you might have had in mind, is to submit a callback (or a coroutine using asyncio.run_coroutine_threadsafe
) to an event loop running in another thread. Here is an example:
import asyncio, threading
def hello(thread_name):
print('hello from thread {}!'.format(thread_name))
event_loop_a = asyncio.new_event_loop()
event_loop_b = asyncio.new_event_loop()
def run_loop(loop):
asyncio.set_event_loop(loop)
loop.run_forever()
threading.Thread(target=lambda: run_loop(event_loop_a)).start()
threading.Thread(target=lambda: run_loop(event_loop_b)).start()
event_loop_a.call_soon_threadsafe(lambda: hello('a'))
event_loop_b.call_soon_threadsafe(lambda: hello('b'))
event_loop_a.call_soon_threadsafe(event_loop_a.stop)
event_loop_b.call_soon_threadsafe(event_loop_b.stop)
在这种情况下,很少需要有多个事件循环线程——您通常只创建一个,并允许该线程满足您所有的异步需求.毕竟,能够在单个事件循环中承载大量任务是 asyncio 的强项之一.
In that case it is rarely needed to have more than one event loop thread - you'd typically create only one, and allow that thread to service all your asyncio needs. After all, being able to host a large number of tasks in a single event loop is one of the strong points of asyncio.
这篇关于如何在 Python 中为线程设置异步事件循环?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!