Python Tornado autoreload模块配置后失效问题求助
Tornado autoreload 模块内配置后无法正常工作的原因与解决
问题场景
我在自定义的MyTornadoApp类中配置了autoreload功能,初始化时调用tornado.autoreload.start(),但实际运行时只有在主脚本的main()函数中再次调用该方法,autoreload才能触发重载。同时重复调用会出现警告:tornado.autoreload started more than once in the same process。
自定义模块代码(tornadoapp.py)
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()
主脚本代码
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())
原因分析
这不是Bug,是Tornado autoreload的运行机制特性,核心原因如下:
- 事件循环未初始化时调用start()无效:在
MyTornadoApp.__init__中调用tornado.autoreload.start()时,asyncio的事件循环还未启动(asyncio.run()在主入口代码中才执行)。Tornado的autoreload依赖活跃的事件循环定时检查文件变化,没有事件循环的情况下,start()无法启动监听任务。 - 重复调用start()的警告原因:在
main()中再次调用start()时,事件循环已初始化,autoreload成功启动,但之前在__init__中的调用是无效的,重复调用就会触发警告——该警告无害,但说明首次调用未起到作用。 - settings配置的作用:你已经在
Application的settings中设置了autoreload=True,Tornado会在服务启动时自动处理autoreload初始化,前提是事件循环已准备好。手动提前调用watch()和start()反而打乱了默认流程。
正确配置方式
不需要手动调用tornado.autoreload.start(),只需遵循以下步骤:
修改后的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} self.tornado = tornado.web.Application(self.default_handlers, **self.options) self._monitoring_file = os.path.abspath('autoreload') def setup_autoreload(self): """Setup custom autoreload watches after event loop is ready""" if not self.options['autoreload']: return print("Setting up autoreload for tornado...") if not os.path.isfile(self._monitoring_file): with open(self._monitoring_file, 'w', encoding='UTF-8') as f: f.write('Do NOT delete. Monitoring changes in this file!') tornado.autoreload.watch(self._monitoring_file) # 无需手动调用start(),Tornado会自动处理
修改后的主脚本
import asyncio import tornado.web from tornadoapp import MyTornadoApp async def main(): app.setup_autoreload() 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())
额外说明
- 如果开启
debug=True,Tornado会自动启用autoreload、取消模板缓存等调试特性,此时无需单独设置autoreload=True。 - 手动调用
tornado.autoreload.start()只有在事件循环已经启动的情况下才有效,否则无法创建定时检查任务。
内容的提问来源于stack exchange,提问作者bgeneto
相关产品推荐
相关产品推荐

