При использовании @run_on_executor в торнадо ошибка не связана с текущим циклом событий в потоке ThreadPoolExecutor-0_0 - PullRequest
0 голосов
/ 13 мая 2019

Я выполняю метод write_message websocket в обработчике, я сообщу об ошибке.

class Test_Handler(BaseHandler):

    @run_on_executor
    def get(self):
        host_name = 'Win10'
        ws = WebSocketHandler.clients[host_name]['self']
        ws.write_message(json.dumps({
            'status': 203,  # 状态201是为启动机器人
        }))
        return self.write({'status': 200})
  File "D:\Anaconda3\lib\site-packages\tornado\websocket.py", line 256, in write_message
    return self.ws_connection.write_message(message, binary=binary)
  File "D:\Anaconda3\lib\site-packages\tornado\websocket.py", line 801, in write_message
    fut = self._write_frame(True, opcode, message, flags=flags)
  File "D:\Anaconda3\lib\site-packages\tornado\websocket.py", line 780, in _write_frame
    return self.stream.write(frame)
  File "D:\Anaconda3\lib\site-packages\tornado\iostream.py", line 536, in write
    future = Future()
  File "D:\Anaconda3\lib\asyncio\events.py", line 694, in get_event_loop
    return get_event_loop_policy().get_event_loop()
  File "D:\Anaconda3\lib\asyncio\events.py", line 602, in get_event_loop
    % threading.current_thread().name)
RuntimeError: There is no current event loop in thread 'ThreadPoolExecutor-0_0'.

Ответы [ 2 ]

1 голос
/ 14 мая 2019

Вы не должны вызывать никакие методы Tornado (кроме IOLoop.add_callback) из другого потока.Это включает в себя темы, созданные исполнителями.Использовать исполнителей при вызове синхронного кода;они не нужны для асинхронного кода, написанного для Tornado, и я не вижу причин использовать его в этом фрагменте.

В общем, предпочтительнее использовать IOLoop.run_in_executor вместо @run_on_executor декоратора, потому что это делает переходы между асинхронным и синхронизирующим режимами более явными.

0 голосов
/ 25 июня 2019

Убедитесь, что класс Test_Handler содержит два члена:

def __init__(self, *args, **kwargs):
    self.executor = tornado.concurrent.futures.ThreadPoolExecutor(...)
    self.io_loop = tornado.ioloop.IOLoop.current()
...