gpt4 book ai didi

Python - 在单独的子进程或线程中运行 Autobahn|Python asyncio websocket 服务器

转载 作者:IT老高 更新时间:2023-10-28 20:39:52 31 4
gpt4 key购买 nike

我有一个在 Python 3.4.1 中运行的基于 tkinter 的 GUI 程序。我在程序中运行了几个线程来从各种 url 获取 JSON 数据。我想添加一些 WebSocket 功能,以便能够允许程序充当服务器并允许多个客户端通过 WebSocket 连接到它并交换其他 JSON 数据。

我正在尝试将 Autobahn|Python WebSocket 服务器用于异步。

我首先尝试在 GUI 程序下的单独线程中运行 asyncio 事件循环。但是,每次尝试都会给出 'AssertionError: There is no current event loop in thread 'Thread-1'。

然后我尝试使用标准库多处理包生成一个进程,该包在另一个进程中运行 asyncio 事件循环。当我尝试这个时,我没有得到任何异常,但 WebSocket 服务器也没有启动。

是否可以在另一个 Python 程序的子进程中运行异步事件循环?

有没有办法将 asyncio 事件循环集成到当前的多线程/tkinter 程序中?

更新下面是我尝试运行以进行初始测试的实际代码。

from autobahn.asyncio.websocket import WebSocketServerProtocol
from autobahn.asyncio.websocket import WebSocketServerFactory
import asyncio
from multiprocessing import Process

class MyServerProtocol(WebSocketServerProtocol):

def onConnect(self, request):
print("Client connecting: {0}".format(request.peer))

def onOpen(self):
print("WebSocket connection open.")

def onMessage(self, payload, isBinary):
if isBinary:
print("Binary message received: {0} bytes".format(len(payload)))

else:
print("Text message received: {0}".format(payload.decode('utf8')))

## echo back message verbatim
self.sendMessage(payload, isBinary)

def onClose(self, wasClean, code, reason):
print("WebSocket connection closed: {0}".format(reason))

def start_server():
factory = WebSocketServerFactory("ws://10.241.142.27:6900", debug = False)
factory.protocol = MyServerProtocol
loop = asyncio.get_event_loop()
coro = loop.create_server(factory, '10.241.142.27', 6900)
server = loop.run_until_complete(coro)
loop.run_forever()
server.close()
loop.close()


websocket_server_process = Process(target = start_server)
websocket_server_process.start()

其中大部分直接来自 Autobahn|Python 的异步示例代码。如果我尝试将它作为进程运行,它不会做任何事情,没有客户端可以连接到它,如果我运行 netstat -a 则没有使用端口 6900。如果只是在主程序中使用 start_server(),它会创建 WebSocket 服务器。

最佳答案

首先,您会收到 AssertionError: There is no current event loop in thread 'Thread-1'. 因为 asyncio 要求程序中的每个线程都有自己的自己的事件循环,但它只会在主线程中自动为您创建一个事件循环。因此,如果您在主线程中调用 asyncio.get_event_loop 一次,它将自动创建一个循环对象并将其设置为您的默认值,但如果您在子线程中再次调用它,您将得到那个错误。相反,您需要在线程启动时显式创建/设置事件循环:

loop = asyncio.new_event_loop()
asyncio.set_event_loop(loop)

完成此操作后,您应该能够在该特定线程中使用 get_event_loop()

可以在通过 multiprocessing 启动的子进程中启动 asyncio 事件循环:

import asyncio
from multiprocessing import Process

@asyncio.coroutine
def coro():
print("hi")

def worker():
loop = asyncio.get_event_loop()
loop.run_until_complete(coro())

if __name__ == "__main__":
p = Process(target=worker)
p.start()
p.join()

输出:

hi

唯一需要注意的是,如果您在父进程和子进程中启动事件循环,如果您在 Unix 平台上,则需要在子进程中显式创建/设置一个新事件循环(由于bug in Python)。它应该可以在 Windows 上正常工作,或者如果您使用 'spawn' multiprocessing 上下文。

我认为应该可以在 Tkinter 应用程序的后台线程(或进程)中启动 asyncio 事件循环,并同时拥有 tkinter asyncio 事件循环并行运行。如果您尝试从后台线程/进程更新 GUI,您只会遇到问题。

关于Python - 在单独的子进程或线程中运行 Autobahn|Python asyncio websocket 服务器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25063403/

31 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com