线程中的python3 websocket
Posted
技术标签:
【中文标题】线程中的python3 websocket【英文标题】:python3 websocket in thread 【发布时间】:2019-10-30 01:39:10 【问题描述】:我有一个简单的 python tkinter gui,只有几个按钮。当按下按钮时,我想做的就是启动 websocket 连接并开始接收。我可以正常运行代码,但是一旦我尝试将其放入线程中,就会出现错误
RuntimeError: There is no current event loop in thread
所以先试试吧:
import websockets
websocket = websockets.connect(uri, ssl = True)
websocket.recv()
我得到了错误
"Connect object has no attribute 'recv'"
这很奇怪,当我以不同的方式运行它时,我没有收到该错误 当我完全按照文档操作时
def run_websockets2(self):
async def hello():
uri = Websocket_Feed
# with websockets.connect(uri, ssl=True) as websocket:
socket = await websockets.connect(uri, ssl=True)
self.web_socket = socket
while self.running:
greeting = await socket.recv()
print(f"< greeting")
asyncio.get_event_loop().run_until_complete(hello())
只要我调用“websockets2()”,它就可以工作。但如果我尝试做
self.websocket_thread = threading.Thread(target=self.run_websockets2, args=())
self.websocket_thread.start()
我得到了错误
RuntimeError: There is no current event loop in thread 'web_sockets'
当我使整个函数非异步时,我得到一个错误
def run_websockets(self):
uri = Websocket_Feed
# with websockets.connect(uri, ssl=True) as websocket:
socket = websockets.connect(uri, ssl=True)
self.web_socket = socket
while self.running:
greeting = socket.recv()
print(f"< greeting")
我得到了错误 RuntimeError:线程“web_sockets”中没有当前事件循环。在 socket = websockets.connect(uri, ssl=True)
我不明白为什么我不能简单地在一个线程中运行这些非异步。非常感谢任何帮助
【问题讨论】:
【参考方案1】:您在这里有几个不同的错误,这使图片有些混乱。一、关于:
"Connect object has no attribute 'recv'"
...这只是说websocket
对象没有称为recv
的方法
您遇到的主要问题是尝试从生成的线程调用run_websockets2()
。 IE。从主线程调用此方法有效,但从新线程调用此方法失败。
这是预期的行为。这是因为在衍生线程(即主线程以外的线程)中,没有定义异步事件循环。但是为了方便起见,在主线程中定义了一个。因此 asyncio 知道您是从衍生线程还是主线程调用,并且行为不同。有关详细说明,请参阅此答案。 Why asyncio.get_event_loop method checks if the current thread is the main thread?
要解决您的问题,您可以为每个生成的线程创建一个新的事件循环,这样代码将变为:
event_loop = asyncio.new_event_loop()
event_loop.run_until_complete(hello())
而不是
asyncio.get_event_loop().run_until_complete(hello())
或者,您可以将event_loop
存储在一个公共位置,并允许所有生成的线程重用该事件循环。
【讨论】:
感谢@Darren Smith。我认为 pthon 在这种情况下的行为方式很奇怪,但您的答案是正确的。我不知道异步的东西是如何工作的。【参考方案2】:感谢@Darren Smith,我想发布我是如何实际解决我的代码的。我只是添加了一行代码 "asyncio.set_event_loop(asyncio.new_event_loop())" 到顶部。
def run_websockets2(self):
asyncio.set_event_loop(asyncio.new_event_loop())
async def hello():
uri = Websocket_Feed
# with websockets.connect(uri, ssl=True) as websocket:
socket = await websockets.connect(uri, ssl=True)
self.web_socket = socket
while self.running:
greeting = await socket.recv()
print(f"< greeting")
asyncio.get_event_loop().run_until_complete(hello())
我不得不承认,我喜欢 python,但是让代码根据其上下文从根本上以不同的方式运行,并且修复是与上下文无关的一行代码,这似乎是一种非常糟糕的形式。
【讨论】:
以上是关于线程中的python3 websocket的主要内容,如果未能解决你的问题,请参考以下文章