我试图创建两个线程,每个线程都有自己的asyncio事件循环.

我try 了以下代码,但似乎不起作用:

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异步函数.

推荐答案

线程在各自的事件循环中对回调进行排队,但它们在实际执行事件循环之前退出,因此回调永远不会执行.此外,您不需要call_soon_threadsafe,因为您正在从事件循环运行(或者更确切地说,将运行)的同一线程调用回调.

此代码打印预期的输出:

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的一个更典型的用例,更符合您的 idea ,是向另一个线程中运行的事件循环提交回调(或使用asyncio.run_coroutine_threadsafe的协同路由).下面是一个例子:

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需求.毕竟,能够在单个事件循环中承载大量任务是asyncio的优点之一.

Python-3.x相关问答推荐

根据样本量随机 Select 组内样本

如何将CSV或FDF数据解析到Python词典并注入到模板PDF表单中?

我用Kivy创建的应用程序在安卓系统上运行时出错.(attributeerror:';class';对象没有属性';_javaclass__cls_storage';)

检测点坐标 - opencv findContours()

将自定义函数应用于 pandas 数据框的每一列

Python 舍入数字不准确

如何在类中的函数(以 self 作为第一个参数)中使用递归

Pandas:从 Pandas 数据框中的 1 和 0 模式中获取值和 ID 的计数

如何使用`re.findall`从字符串中提取数据

获取字符串中的两个工作日之间的差异

为什么 return node.next 会返回整个链表?

Python defaultdict 在获取时返回 None,尽管使用默认值初始化

每个数据行中每个数据帧值的总和

如何从字典中打印特定键值?

如何调试垂死的 Jupyter Python3 内核?

计数大于Pandas groupby 中的值的项目

python - 使用 matplotlib 和 boto 将绘图从内存上传到 s3

我可以替换 Python 中对象的现有方法吗?

如何在 Python 3.4 中使用 pip 3?

交错4个相同长度的python列表