在Quarto仪表板嵌入Shinylive应用时遇Pyodide安装shiny包错误
问题分析与解决方案
核心问题拆解
- Shinylive环境依赖未正确安装:添加
micropip.install('shiny')后未处理异步逻辑,且缺少Excel读取必需的openpyxl依赖 - UI违规调用Server端函数:UI代码直接调用Server内的
dat()响应式函数,违反Shiny前后端分离规则 - 数据筛选语法错误:
isin是方法需用括号调用,且输入控件ID与代码引用不匹配 - 文件路径适配问题:Shinylive独立模式下,路径处理需适配Pyodide文件系统逻辑
分步解决
1. 正确安装依赖
在Shinylive代码块最顶部添加异步安装逻辑,确保所有依赖在import前完成安装:
import micropip await micropip.install(["shiny", "pandas", "numpy", "seaborn", "openpyxl"])
注:
openpyxl是Pandas读取Excel的必需依赖,必须包含
2. 修正UI与Server交互逻辑
UI中初始将选择器设为空列表,在Server端通过update_select_input动态加载选项:
- UI部分:将
choices参数设为[] - Server部分:添加
@reactive.effect装饰的函数更新选择器选项
3. 修复数据筛选语法错误
将错误的筛选代码:
dat().loc[dat()[['item']].isin[input.select_item()]]
替换为:
dat().loc[dat()['item'].isin(input.select_items())]
修正点:
isin()用括号调用,控件ID统一为select_items,直接对item列进行匹配
4. 适配Shinylive文件路径
Shinylive独立模式下,通过Quarto的#| files:指令声明依赖文件,路径简化为相对路径即可:
#| files: #| - dat/filename.xlsx
修改后的完整代码
index.qmd中的Shinylive代码块
```{shinylive-python} #| standalone: true #| title: Grouped Bar Plot - NOV 2023 #| files: #| - dat/filename.xlsx import micropip await micropip.install(["shiny", "pandas", "numpy", "seaborn", "openpyxl"]) from shiny import * import pandas as pd import numpy as np import seaborn as sns # UI app_ui = ui.page_fluid( ui.input_select( "select_items", "选择项目:", choices=[], # 初始为空,由Server动态填充 multiple = True ), ui.output_plot("plot") ) # server def server(input, output, session): @reactive.calc def dat(): df_summary = pd.read_excel("dat/filename.xlsx", sheet_name="sheet_name", usecols="A:D", dtype={"item": str, "value": np.float64, "value2": np.float64}) df_summary_grp = df_summary.melt(id_vars='item', value_vars=['value1', 'value2'], var_name='variable', value_name='values') return df_summary_grp @reactive.effect def _update_select(): # 动态更新选择器选项 update_select_input(session, "select_items", choices=dat()["item"].unique().tolist()) @output @render.plot(alt="分组条形图") def plot(): # 处理未选择任何项目的边界情况 if not input.select_items(): filtered_df = dat() else: filtered_df = dat().loc[dat()["item"].isin(input.select_items())] g_ax_item_grp = sns.barplot(y='item', x='values', hue='variable', data=filtered_df) g_ax_item_grp.set_xlabel(None) sns.move_legend(g_ax_item_grp, loc="lower center", bbox_to_anchor=(-.4,-.3), ncol=2, title=None, frameon=False) return g_ax_item_grp # app app = App(app_ui, server)
### 额外注意事项 - 确保`dat/filename.xlsx`文件存在于项目根目录下,Quarto会自动打包该文件到Shinylive环境 - `_quarto.yml`中的`filters: [shinylive]`配置无需修改 内容的提问来源于stack exchange,提问作者M. Wood
相关产品推荐
相关产品推荐

