Связанная с проблемой сопрограмма ‘AsyncSocketClient.connect’ никогда не ожидалась Торнадо (сокет)

#python #sockets #asynchronous #async-await #tornado

#python #сокеты #асинхронный #асинхронный-ожидание #торнадо

Вопрос:

Я работаю над установлением соединения с сокетами (веб-платформа Tornado).)

Мой код:

main.py

 def main():
    io_loop = tornado.ioloop.IOLoop.instance()
    decoder = AsyncSocketClient(host = "localhost", port = 8080, try_reconnect=True , io_loop= io_loop)
    decoder.connect()
    io_loop.start()

if __name__ == '__main__':
    main()
  

AsyncSocketClient.py

 class AsyncSocketClient():
    def __init__(self, host,io_loop , port, try_reconnect=False):
        self.ws_host = host
        self.ws_port = port
        self.io_loop = io_loop

    async def connect(self):
        class AsyncSocket(socket.socket):
            def write_message(self, message):
                message = message.encode()
                self.send(message)
        try:
            self._ws_connection = AsyncSocket(socket.AF_INET, socket.SOCK_STREAM, 0)
            self._ws_connection.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
            await self._ws_connection.connect((self.ws_host, self.ws_port))
            self._ws_connection.setblocking(0)
            self.add_to_ioloop(self.io_loop)
            self._on_connection_success()
        except Exception as e:
            time.sleep(1)
            self.close()

    def add_to_ioloop(self, io_loop):
        io_loop.add_handler(self._ws_connection.fileno(), self._handle_events, io_loop.ERROR)
        io_loop.update_handler(self._ws_connection.fileno(), io_loop.READ)

    async def close(self):
        if not self._ws_connection:
            raise RuntimeError('Web socket connection is already closed.')

        await self._ws_connection.close()
        self._ws_connection = None
        self._on_connection_close()

    async def _on_connection_close(self):
        print("Connection Closed from "   self.ws_host   ":"   str(self.ws_port))
        if self.try_reconnect:
            print("Retrying to connect "   self.ws_host   ":"   str(self.ws_port))
            self.connect()

    def _on_connection_success(self):
        print("Connected to "   self.ws_host   ":"   str(self.ws_port))

  

Когда я запускаю main.py , я получаю следующую ошибку:

 main.py: RuntimeWarning: coroutine 'AsyncSocketClient.connect' was never awaited
  decoder.connect()
  

Я пытался использовать метод run_sync (), но мне не удалось добиться результата. Я передал лямбда run_sync() -выражение, и я смог подключиться, но после выполнения этой строки ничего не произошло:

await self._ws_connection.connect((self.ws_host, self.ws_port))

Ответ №1:

Поскольку connect это сопрограмма, вам это нужно await . И для этого вам также придется преобразовать main функцию в сопрограмму.

Но это просто кажется излишним, потому что вы можете добиться аналогичного эффекта, используя run_sync :

 if __name__ == '__main__':
    decoder = AsyncSocketClient(...)
    io_loop = tornado.ioloop.IOLoop.current()
    io_loop.run_sync(decoder.connect)
  

Кстати, если вы пытаетесь внедрить клиент websocket, знайте, что tornado уже поставляется с ним.

Комментарии:

1. Я попробовал io_loop.run_sync (decoder.connect) Но я получаю сообщение об ошибке: нетип объекта не может быть использован в выражении ‘await’ Эта ошибка возникает в этой строке: await self._ws_connection.connect((self.ws_host, self.ws_port))

2. @SharvinShah Это потому socket.connect , что метод не является сопрограммой. Следовательно, вы не можете await этого сделать. Для асинхронных сокетов используйте потоки tcpclient или asyncio от tornado .