从脚本运行Python Shiny应用时reload功能报错的解决办法
Python Shiny应用自动重载(reload)功能无法启用的解决办法
问题背景
我尝试直接从脚本运行Python Shiny示例应用,代码如下:
"""Test shiny app.""" import argparse from shiny import App, render, ui app_ui = ui.page_fluid( ui.input_slider("n", "N", 0, 100, 20), ui.output_text_verbatim("txt"), ) def server(input, output, _session): @output @render.text def txt(): return f"n*2 is {input.n() * 2}." app = App(app_ui, server) if __name__ == "__main__": ap = argparse.ArgumentParser(description="Parse args passed into the Shiny app") ap.add_argument("--host", help="URL of host", default="127.0.0.1") ap.add_argument("--port", help="Port to use", type=int, default=8888) ap.add_argument("--reload", help="Enable auto-reload", action=argparse.BooleanOptionalAction, default=True) args = ap.parse_args() app.run(host=args.host, port=args.port, reload=args.reload)
在已安装Shiny的Python环境中执行命令:
python test_app.py
执行时出现以下警告:
WARNING: Current configuration will not reload as not all conditions are met,please refer to documentation. WARNING: You must pass the application as an import string to enable 'reload' or 'workers'.
当设置reload=False时应用可正常运行,请问是否有解决办法让reload功能正常启用?
(编辑:已修复@relent95在回答中指出的argparse问题)
解决办法
方法1:使用Shiny官方CLI工具运行(推荐)
自动重载功能设计为配合Shiny的命令行工具使用,需要通过导入字符串(格式为模块名:应用对象)指定要运行的应用。
假设你的脚本文件名为test_app.py,其中导出的应用对象是app,执行以下命令即可启用重载:
shiny run --reload test_app:app
如果需要指定host和port,可添加对应参数:
shiny run --reload --host 127.0.0.1 --port 8888 test_app:app
方法2:调整脚本运行逻辑(不推荐)
如果坚持要通过python test_app.py的方式运行,可以修改脚本,让它在检测到reload参数时,通过Shiny的CLI接口间接启动应用(本质上还是利用导入字符串机制)。示例代码如下:
"""Test shiny app.""" import argparse from shiny import run_app from shiny import App, render, ui app_ui = ui.page_fluid( ui.input_slider("n", "N", 0, 100, 20), ui.output_text_verbatim("txt"), ) def server(input, output, _session): @output @render.text def txt(): return f"n*2 is {input.n() * 2}." app = App(app_ui, server) if __name__ == "__main__": ap = argparse.ArgumentParser(description="Parse args passed into the Shiny app") ap.add_argument("--host", help="URL of host", default="127.0.0.1") ap.add_argument("--port", help="Port to use", type=int, default=8888) ap.add_argument("--reload", help="Enable auto-reload", action=argparse.BooleanOptionalAction, default=True) args = ap.parse_args() if args.reload: # 通过导入字符串启动,启用重载 run_app("test_app:app", host=args.host, port=args.port, reload=True) else: # 直接运行,不启用重载 app.run(host=args.host, port=args.port, reload=False)
原因说明
警告提示的核心逻辑是:自动重载需要监控应用模块的文件变化,这要求应用是通过导入字符串的方式加载的——这样重载机制可以在文件修改时重新导入模块并重建应用对象。而直接在脚本中调用app.run()时,应用已经在当前进程中初始化,无法满足重载的前置条件。
内容的提问来源于stack exchange,提问作者Devil
相关产品推荐
相关产品推荐

