Python 3.x ValueError在单独的线程中调用asyncio.run()时出错

Python 3.x ValueError在单独的线程中调用asyncio.run()时出错,python-3.x,multithreading,python-asyncio,valueerror,Python 3.x,Multithreading,Python Asyncio,Valueerror,我有一个网络应用程序,它正在多个套接字上侦听。 为了单独处理每个套接字,我使用Python的threading.Thread模块 这些套接字必须能够在数据包接收时运行任务,而不会延迟来自套接字处理线程的任何进一步数据包接收 为此,我用关键字async声明了运行前面提到的任务的方法,这样我就可以用asyncio.run(my_async_任务(my_参数))异步运行它们了。 我已经在单个套接字(在主线程上运行)上测试了这种方法,并取得了巨大成功。 但当我使用多个套接字(每个套接字都有独立的处理程序

我有一个网络应用程序,它正在多个套接字上侦听。 为了单独处理每个套接字,我使用Python的
threading.Thread
模块

这些套接字必须能够在数据包接收时运行
任务
,而不会延迟来自套接字处理
线程的任何进一步数据包接收

为此,我用关键字
async
声明了运行前面提到的
任务的方法,这样我就可以用
asyncio.run(my_async_任务(my_参数))异步运行它们了。

我已经在单个套接字(在
主线程
上运行)上测试了这种方法,并取得了巨大成功。 但当我使用多个套接字(每个套接字都有独立的
处理程序线程
)时,会引发以下异常:

ValueError: set_wakeup_fd only works in main thread
我的问题如下:
asyncio
是适合我需要的工具吗?如果是,如何从非主线程的线程运行
async
方法

我的大多数搜索结果都包括“事件循环”和“等待”
assync
results(如果我正确理解这些结果的话),这不是我想要的

我在这个问题中谈论套接字是为了提供上下文,但我的问题主要是关于
子线程中
asyncio
的行为

如果需要,我可以编写一个简短的代码示例来重现错误。 谢谢你的帮助

Edit1,下面是一个最小的可复制代码示例:

导入异步IO
导入线程
导入时间
#在不中断侦听线程的情况下处理来自任何套接字的特定数据包
异步定义句柄(val):
打印(“已处理:{}”。格式(val))
#用于模拟线程套接字Listener的类
MyFakeSocket类(threading.Thread):
定义初始值(self,val):
threading.Thread.\uuuuu init\uuuuuu(自)
self.val=val#假接收数据包的值
def运行(自):
对于范围(10)内的i:
#(假)套接字将依次接收[val,val+1,…val+9]
asyncio.run(handle_it(self.val+i))
睡眠时间(0.5)
#入口点
套接字=MyFakeSocket(0),MyFakeSocket(10)
对于插座中的插座:
socket.start()

这可能与此处讨论的错误有关:

如果是这样,这将是windows上python 3.8的一个问题。为了解决这个问题,您可以尝试降级到python 3.7,它不包括asyncio.main,因此您需要手动获取并运行事件循环,如:

loop = asyncio.get_event_loop()
loop.run_until_complete(<your tasks>)
loop.close()
loop=asyncio.get\u event\u loop()
循环。运行_直到_完成()
loop.close()

否则,您能否在docker容器中运行代码?这可能适用于您,然后将与操作系统行为分离,但要做的工作要多得多

你的例子对我来说没有错。这是给你的吗?你有什么版本的python?@Piratenijas,我正在使用python 3.8。我目前正在Windows上开发,主要是因为服务器在这个操作系统上运行,但我希望它是多平台的(至少像Windows和debian一样)@Piratenijas它是否为您打印输出?(即使它由于并发打印而变得杂乱无章?)它也会打印大量“已处理”的消息,这似乎是正确的。如果这有什么不同的话,我现在在ubuntu 18.04上。好吧,看起来确实是预期的行为。。。认为python是支持多平台的好脚本语言。(这实际上是我们选择这种语言的主要原因):(这似乎是问题的根源。事实上,我不知道在我的任何研究中,这个问题是如何没有出现的。但是,我希望尽可能保持python支持的版本(以减少后续的维护任务)。您认为手动处理循环在3.8 python版本中会起作用吗?或者这种用法会被贬低吗?手动处理在python 3.8中肯定会起作用。但我无法测试错误是否仍然会发生,因为它只是windows。我想它很快就会被修补,所以请留意我建议的3.8修补程序dation.似乎是最好的行动方案!在我接受答案之前还有最后一个问题。如上所述,我希望我的“MyFakeSocket”能够继续运行(run方法),即使“task”函数仍在执行(其中一些函数/过程实际上可能需要很长时间才能完成)。我不会“在完成之前运行”在继续for循环(在“MyFakeSocket.run()”中)之前等待任务结束?关于Docker,我在过去已经多次使用它,但仅用于CI,因此我可以构建一个Docker映像(不要认为这会花费我太多时间),但是你能“分发”Docker映像吗?如果是的话,会不会有大量开销(就应用程序大小而言)?如果脱离for循环,您可能需要使用一个单独的函数来创建和等待所有的协程,然后在事件循环中运行。我不是100%了解如何做到这一点!至于docker,您可以分发它,但在您的情况下,这听起来似乎是不必要的开销,所以请忽略该建议!