繁体   English   中英

Python 在模块中配置时龙卷风自动重新加载不工作

[英]Python tornado autoreload not working when configured in a module

我试图弄清楚为什么 Python Tornado 自动重载功能在模块内部配置和启动时不起作用。 以下模块包含一个MyTornadoApp class,如果设置了正确的选项,它会配置并启动 autoreload:

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 应用程序,但不幸的是,只有在调用startautoreload才有效(同样,根据 Tornado 发出的警告消息)。 任何ideias为什么会这样? 它是功能还是错误? 我错过了什么? TIA。

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 但是,如果我们从main() function 中删除tornado.autoreload.start()行,那么如果我们更改监控文件(或任何其他监视文件),将不会触发自动重载。

这是asyncio.run的一个不幸的怪癖/缺陷:它会默默地丢弃线程中已经存在的任何事件循环,并创建一个新的事件循环来运行主 function。由于 Tornado 在构建应用程序时初始化 autoreload,这意味着它使用在main之外构造它时的错误事件循环。

有两种可能的解决方案:

  1. 使用asyncio.get_event_loop().run_until_complete()而不是asyncio.run() 这应该按照您期望的方式工作,但这种用法已被弃用,并将在 python 的某个未来版本中删除。
  2. 继续使用asyncio.run() ,但在主 function 中执行所有操作(包括应用程序的构建)。这是未来推荐的模式。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM