动态添加Python闪亮服务器模块的问题

问题描述 投票:0回答:1

简单的问题是,如何实例化任意一组服务器模块?我的 UI 模块按预期呈现,但我看到有迹象表明按钮每次单击都会触发多个服务器模块响应(不增加按钮值)或根本不触发服务器模块。

我正在寻找有关如何做得更好或我可能做错了什么的建议。

目标是创建一个根据外部文件内容进行更新的 UI(本质上是每行一个新的折叠面板)。服务器模块还可以清除该文件中的行(以及 UI 中的元素),使其成为循环。我读取了文件的内容(由

reactive.file_reader()
监控),并循环遍历各行以实例化新的服务器和 UI 模块。每次更新外部文件时都会运行循环。

每次文件更新时,我可能会创建多个相同的模块实例,但我不能确定。 UI 根据需要呈现和导航。单击“停止运行”按钮后,查看多个手风琴元素和模式对话框。实验第一次在会话中结束时,外部文件和 UI 将按预期更新。第二次创建两个对话框:第一个仅注册“保持实验运行”按钮,第二个对话框接受任一按钮并在 UI 中提供适当的响应。所有后续“结束实验”的尝试都无法在服务器中做出任何响应。有关以下症状的更多详细信息。

代码如下所示:

@reactive.file_reader(watched_file):
def data():
   do_stuff
   return list_of_desired_modules

@reactive.effect
@reactive.event(data)
@def _():
   server_list=[]
   ui_list = []
   for item in data():
      server_list.append(server_module_instance(item, args....) #server logic to populate graph,etc in UI
      ui_list.append(ui_module_instance(item, args....) #returns accordion_panel object
   @output
   @render.ui
   def dynamic_ui():
      return ui.accordion(*ui_list, id ="dynamic_accordion")
   return server_list

我检查了浏览器中的元素,以确认所有按钮都具有从其模块实例继承的唯一名称。

我策略性地放置了

print
命令来报告单击按钮时发生的情况。

@reactive.Effect
@reactive.event(input.stop_run)
def _():
  print("stop_run registered", input.stop_run() )
  confirm_stop = ui.modal("Are you sure you want to stop this run?",
    title = "Stop Run?",
    footer= ui.row(ui.column(6,ui.modal_button("Keep Experiment Running")), 
      ui.column(6,ui.input_action_button("commit_stop", "End the Experiment"))),
      easy_close= False,
      )
  ui.modal_show(confirm_stop
@reactive.Effect
@reactive.event(input.commit_stop)
def _():
  print(input.commit_stop(), "commit stop value")
  ... a bunch of other stuff, including removing a record from the watched_file...

对于我尝试停止多次运行的新会话,我得到以下打印结果:

#click stop_run on a module/accordion
stop_run registered 1             #one click, one increment, one print
1 commit stop value               #modal dialog and everything works

...
#click stop on another module/accordion
stop_run registered 1             #one click, one increment, two prints
stop_run registered 1
1 commit stop value               #two modal dialogs show up, 
                                  #first only accepts the modal_button, 
                                  #second accepts action button
...
#click stop on another module/accordion
stop_run registered 1             #once click, one increment, three prints
stop_run registered 1
stop_run registered 1 
                                  #one modal shows, action button is unresponsive, 
                                  #modal button closes modal dialog
...
#click again on same module/accordion
stop_run registered 2             #one click, one increment, three prints, same behavior as previous
stop_run registered 2
stop_run registered 2

我尝试使用

ui.remove_ui()
删除可疑的预先存在的模块(在循环内,在 UI 和服务器列表中返回新副本之前),但这会产生一个没有任何 UI 的空白空间。

我已经研究了

ui.insert_accordion()
ui.remove_accordion()
,但它们没有我需要的图形、模式对话框和按钮的服务器逻辑,如链接图像所示。

shiny for python 网页上的所有动态 UI 或模块示例都有硬编码的模块数量,这些模块要么显示,要么隐藏。不是动态创建模块调用的示例。

python dashboard py-shiny dynamic-ui
1个回答
0
投票

TLDR:在创建新的服务器/ui 模块 ID 时添加一个计数器。每次执行循环时递增。希望这是可以推广的。

一开始的故障排除尝试最终修复了该行为。由于每次运行带有服务器/ui 列表循环的块时,问题似乎都会增加,因此我决定向模块 ID 添加一个计数器。这样,当我检查浏览器中的元素时,我可以判断我是在单击模块的第 0 个实例还是第 N 个实例。这些元素通常是第 N 个元素,但行为是所需的:一次单击、一次打印、一次成功完成下游任务、没有无响应的按钮。

代码如下:

counter = reactive.value(0) #NEW CHANGE: counter = 0 at start of new session

@reactive.file_reader(watched_file):
def data():
   do_stuff
   return list_of_desired_modules

@reactive.effect
@reactive.event(data)
@def _():
   server_list=[]
   ui_list = []
   for item in data():
      server_list.append(server_module_instance(f"{item}_{counter()}", args....) # NEW CHANGE: changed ID to include counter, new ID for same item
      ui_list.append(ui_module_instance(f"{item}_{counter()}", args....) #NEW CHANGE: changed ID to include counter, new ID for same item
 
   counter.set(counter() + 1) #NEW CHANGE:counter increments with every loop
 
   @output
   @render.ui
   def dynamic_ui():
      return ui.accordion(*ui_list, id ="dynamic_accordion")
   return server_list

内存使用量似乎并没有因为后台大量的先前迭代而激增,因此这个解决方案似乎令人满意。希望它们被清理干净。

© www.soinside.com 2019 - 2024. All rights reserved.