Невозможно отправить сообщение websockets внутри класса - PullRequest
2 голосов
/ 06 октября 2019

Я планирую написать класс WebsocketHandler, который обернет пакет websockets

Это код:

import asyncio
import websockets


class WebsocketHandler:
    __connection = None

    def __init__(self):
        asyncio.run(self.__setConnection())

    async def __setConnection(self):
        async with websockets.connect("ws://localhost/your/path") as websocket:
            self.__connection = websocket
            print("Connected")

    def send(self, msg):
        self.__connection.send(msg)
        print("message Send")


ws = WebsocketHandler()
ws.send("message")

Для серверной части у меня есть другойготовый скрипт, который работает (протестирован с другими скриптами на других языках), который отправляет мне сообщение, когда у меня новое соединение, когда я получаю сообщение и когда у меня отключается клиент.

Когда я пытаюсь это сделать скриптуспешно подключиться к моему серверу веб-сокетов (сценарий печати Connected и на стороне сервера я получаю новое подключение).

Затем в моем сценарии появляется предупреждение

RuntimeWarning: coroutine 'WebSocketCommonProtocol.send' was never awaited 
self.__connection.send(msg)

И затем мойсценарий печати Message send и он останавливается.

Проблема в том, что на стороне сервера я не получаю факт наличия сообщения, а только тот, который говорит мне, что клиент отключен. В основном скрипт не отправляет сообщение и не выдает ошибку.

Кто-нибудь знает, в чем проблема?

1 Ответ

2 голосов
/ 09 октября 2019

Проблема в том, что класс WebsocketHandler имеет только один асинхронный метод, а именно __setConnection, который запускается путем вызова функции asyncio.run. документы говорят, что

Эта функция всегда создает новый цикл обработки событий и закрывает его в конце.

То есть это единственныйместо, где может выполняться асинхронный код. Ваш код создает соединение через веб-сокет и закрывает его сразу после того, как напечатает «Подключено». Это происходит потому, что вы вызываете метод websockets.connect с async with в качестве асинхронного диспетчера контекста, который автоматически закрывает соединение при выходе. Это первый недостаток, второй заключается в том, что функция self.__connection.send является сопрограммой , и она не будет работать, пока вы не ожидаете . Это именно то, о чем говорится в сообщении об ошибке. Вот как вы можете исправить класс обработчика websocket:

import asyncio
import websockets


class WebsocketHandler(object):

    def __init__(self):
        self.conn = None

    async def connect(self, url):
        self.conn = await websockets.connect(url)

    async def send(self, msg):
        await self.conn.send(msg)

    async def close(self):
        await self.conn.close()


async def main():
    handler = WebsocketHandler()
    await handler.connect('ws://localhost:8765')

    await handler.send('hello')
    await handler.send('world')

    await handler.close()


loop = asyncio.get_event_loop()
loop.run_until_complete(main())
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...