[英]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. 我正在尝试创建两个线程,每个线程都有自己的asyncio事件循环。
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()
My use case is calling Tornado web framework's websocket_connect async function. 我的用例是调用Tornado web框架的websocket_connect异步函数。
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. 此外,您不需要
call_soon_threadsafe
,因为您正在从同一个线程调用事件循环(或者更确切地说,将要运行)。
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()
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. call_soon_threadsafe
一个更典型的用例,更符合您的想法,是将回调(或使用asyncio.run_coroutine_threadsafe
的协程)提交给在另一个线程中运行的事件循环。 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)
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. 在这种情况下,很少需要有多个事件循环线程 - 您通常只创建一个,并允许该线程为您的所有asyncio需求提供服务。 After all, being able to host a large number of tasks in a single event loop is one of the strong points of asyncio.
毕竟,能够在单个事件循环中托管大量任务是asyncio的优势之一。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.