Автоматическая перезагрузка торнадо Python не работает при настройке в модуле

Я пытаюсь понять, почему функция автоматической перезагрузки Python Tornado не работает при настройке и запуске внутри модуля. Следующий модуль содержит класс MyTornadoApp, который настраивает и запускает автоперезагрузку, если установлена ​​соответствующая опция:

import os
import tornado.autoreload
import tornado.web

class IndexHandler(tornado.web.RequestHandler):
    def get(self):
        self.write("Hello from index handler!")

class MyTornadoApp:
    """Setup my custom tornado app with default settings"""

    # default tornado settings
    default_settings = dict(
        debug=False,
        autoreload=True,
        compress_response=True,
        port=8080,
    )

    default_handlers = [
        (r"/", IndexHandler),
    ]

    def __init__(self, user_settings):
        self.options = {**self.default_settings, **user_settings}

        if self.options['autoreload'] == True:
            self._autoreload_config()

        self.tornado = tornado.web.Application(self.default_handlers,
                                               **self.options)

    def _autoreload_config(self):
        """Setup autoreload for tornado"""
        print("Setting up autoreload for tornado...")
        # autoreload (exclusive) monitor file
        monitoring_file = os.path.abspath('autoreload')
        if not os.path.isfile(monitoring_file):
            with open(monitoring_file, 'w', encoding='UTF-8') as f:
                f.write('Do NOT delete. Monitoring changes in this file!')
        tornado.autoreload.watch(monitoring_file)
        tornado.autoreload.start()

Затем основной скрипт Python, приведенный ниже, создает приложение Tornado, но, к сожалению, autoreload работает только в том случае, если вызывается start (опять же, согласно предупреждающему сообщению Tornado). Любые идеи, почему это происходит? Это фича или баг? Что мне не хватает? ТИА.

import asyncio
import tornado.web
from tornadoapp import MyTornadoApp

async def main():
    ################################################################
    #   Why do I need this in order to autoreload work properly???
    ################################################################
    if app.options['autoreload'] == True:
        tornado.autoreload.start()

    app.tornado.listen(app.options['port'])
    print(f"Tornado is listening on port {app.options['port']}")

    await asyncio.Event().wait()

if __name__ == "__main__":
    my_settings = dict(
        debug=False,
        autoreload=True,
    )
    app = MyTornadoApp(my_settings)
    asyncio.run(main())

Обратите внимание на предупреждающее сообщение: tornado.autoreload started more than once in the same process. Но если мы удалим строку tornado.autoreload.start() из функции main(), то автоперезагрузка не сработает, если мы изменим файл мониторинга (или любой другой отслеживаемый файл).

Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
0
0
92
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Это досадная причуда/недостаток asyncio.run: он молча отбрасывает любой цикл событий, который уже существовал в потоке, и создает новый для запуска основной функции. Поскольку Tornado инициализирует автоперезагрузку при построении приложения, это означает, что он использует неправильный цикл обработки событий, когда вы создаете его вне main.

Есть два возможных решения:

  1. Используйте asyncio.get_event_loop().run_until_complete() вместо asyncio.run(). Это должно работать так, как вы ожидаете, но такое использование устарело и будет удалено в какой-то будущей версии Python.
  2. Продолжайте использовать asyncio.run(), но делайте все (включая построение Приложения) внутри основной функции. Это рекомендуемая схема на будущее.

Другие вопросы по теме