Python 3.5 Asyncio 和多​​个 websocket 服务器 [英] Python 3.5 Asyncio and Multiple websocket servers

查看:42
本文介绍了Python 3.5 Asyncio 和多​​个 websocket 服务器的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在 Ubuntu 上使用 Python websockets 4.0.1.我想要运行 2 个 websocket 服务器.通过为每个线程创建 2 个线程和独立的事件循环,我能够使其成为某种工作".通过某种工作",我的意思是两个 websocket 都可以工作并且响应大约 30 秒,然后其中一个停止.我必须重新启动该过程才能让它们再次工作.如果我只运行这 2 个线程中的一个,单个 websocket 将永远工作.

I am using Python websockets 4.0.1 on Ubuntu. I want to have 2 websocket servers running. I was able to get this to "kind of work" by creating 2 threads and independent event loops for each one. By "kind of work", I mean both websockets work and are responsive for about 30 seconds and then one of them stops. I have to restart the process to get them both to work again. If I only run one or the other of these 2 threads, the single websocket works forever.

我做错了什么,如何让 2 个 websocket 与 asyncio 一起工作?谢谢.

What am I doing wrong and how can I have 2 websockets work forever with asyncio? Thanks.

# Start VL WebSocket Task
class vlWebSocketTask (threading.Thread):
    def __init__(self):
        threading.Thread.__init__(self)
    def run(self):
        # Main while loops
        loop = asyncio.new_event_loop()
        asyncio.set_event_loop(loop)
        while True:
            try:
                print("Starting VL WebSocket Server...")
                startVLServer = websockets.serve(vlWebsocketServer, '192.168.1.3', 8777)
                asyncio.get_event_loop().run_until_complete(startVLServer)  
                asyncio.get_event_loop().run_forever()
            except Exception as ex:
                print(ex)
            time.sleep(5)

# Start IR WebSocket Task
class irWebSocketTask (threading.Thread):
    def __init__(self):
        threading.Thread.__init__(self)
    def run(self):
        loop = asyncio.new_event_loop()
        asyncio.set_event_loop(loop)
        while True:
            try:
                print("Starting IR WebSocket Server...")
                startIRServer = websockets.serve(irWebsocketServer, '192.168.1.3', 8555)
                asyncio.get_event_loop().run_until_complete(startIRServer)  
                asyncio.get_event_loop().run_forever()
            except Exception as ex:
                print(ex)
            time.sleep(5)

# Initialize VL WebSocket Task
#VLWebSocketTask = vlWebSocketTask()
#VLWebSocketTask.start()

# Initialize IR WebSocket Task
IRWebSocketTask = irWebSocketTask()
IRWebSocketTask.start()

推荐答案

您不需要线程来运行多个 asyncio 任务 - 允许多个代理共享相同的事件循环是 asyncio 的强项.您应该能够用这样的代码替换基于线程的类:

You don't need threads to run multiple asyncio tasks - allowing multiple agents to share the same event loop is the strong suit of asyncio. You should be able to replace both thread-based classes with code like this:

loop = asyncio.new_event_loop()
loop.run_until_complete(websockets.serve(vlWebsocketServer, '192.168.1.3', 8777))
loop.run_until_complete(websockets.serve(irWebsocketServer, '192.168.1.3', 8555))
loop.run_forever()

虽然混合线程和 asyncio 并非完全错误,但正确地这样做需要注意不要混淆单独的 asyncio 实例.将线程用于 asyncio 的安全方法是使用 loop.run_in_executor(),它在单独的线程中运行同步代码而不阻塞事件循环,同时返回一个对象 awaitable来自循环.

While it is not exactly wrong to mix threads and asyncio, doing so correctly requires care not to mix up the separate asyncio instances. The safe way to use threads for asyncio is with loop.run_in_executor(), which runs synchronous code in a separate thread without blocking the event loop, while returning an object awaitable from the loop.

注意:上述代码是在 asyncio.run() 出现之前编写的,并手动旋转事件循环.在 Python 3.7 及更高版本中,人们可能会编写如下内容:

Note: the above code was written prior to the advent of asyncio.run() and manually spins the event loop. In Python 3.7 and later one would probably write something like:

async def main():
    server1 = await websockets.serve(vlWebsocketServer, '192.168.1.3', 8777)
    server2 = await websockets.serve(irWebsocketServer, '192.168.1.3', 8555)
    await asyncio.gather(server1.wait_closed(), server2.wait_closed())

asyncio.run(main())

这篇关于Python 3.5 Asyncio 和多​​个 websocket 服务器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆