You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Shiny中使用reactivePoll监控并处理文件变更?

问题描述

我想在Shiny中实现以下功能:

  • 使用自定义读取程序读取源文件
  • 处理数据框并进行渲染
  • 通过自定义文件变更检查器监控源文件,当文件发生变更时重复前两步

我尝试用reactivePoll实现,概念上它是最合适的,但实际操作中遇到了checkFunc未找到、输入参数不被识别等问题。另外我还搞不清reactive、observe、observeEvent这些响应式变量创建方式的区别,以及在这个场景里该怎么用。

下面是我简化后的示例代码:

library(shiny)
library(tidyverse)

#---------生成测试数据-----------
# 创建tibble
id=c('p1','p2','p3')
val=c(2,4,6)
my_data=tibble(id,val)

# 写入csv
file_csv='test.csv'
write_csv(my_data,file_csv)


# 自定义文件检查函数(带参数)
myFileCheck = function(input_path) {
  if (file.exists(input_path))
    file.info(input_path)$mtime[1]
  else
    ""}
# 测试函数
tmp_time = myFileCheck(file_csv)
print(tmp_time)


# 自定义文件读取函数(带参数)
myReadRoutine = function(input_path){
  df = read_csv(input_path, id = 'my_source')
}
# 测试函数
tmp_df=myReadRoutine(file_csv)
print(tmp_df)

#----------Shiny 应用---------
# UI部分
ui = fluidPage(tableOutput('my_data'))

# Server部分
server = function(input, output, session) {
  
  #-----这段能正常运行---
  # 启动时读取数据
  df_shiny=myReadRoutine(file_csv)
  
  # 数据处理用于展示
  df_shiny_display = reactive({df_shiny %>%
      mutate(val2=val*10)})
  
  # 渲染表格
  output$my_data = renderTable(df_shiny_display())
  
  #-----这段无法正常运行----
  # 尝试用自定义文件检查函数监控文件变更,变更时重新读取
  df_shiny = reactivePoll(1000, session, checkFunc = myFileCheck(file_csv), myReadRoutine(file_csv))
}

shinyApp(ui = ui,
         server = server)
解决方案

你的核心问题是对reactivePoll的参数理解有误:checkFunc和valueFunc需要传入无参函数对象,而不是直接传入函数调用的结果。修正后的完整代码如下:

library(shiny)
library(tidyverse)

#---------生成测试数据-----------
id=c('p1','p2','p3')
val=c(2,4,6)
my_data=tibble(id,val)
file_csv='test.csv'
write_csv(my_data,file_csv)

# 自定义文件检查函数
myFileCheck = function(input_path) {
  if (file.exists(input_path))
    file.info(input_path)$mtime[1]
  else
    ""
}

# 自定义文件读取函数
myReadRoutine = function(input_path){
  read_csv(input_path, id = 'my_source')
}

#----------Shiny 应用---------
ui = fluidPage(tableOutput('my_data'))

server = function(input, output, session) {
  # 使用reactivePoll创建响应式数据对象
  df_shiny = reactivePoll(
    intervalMillis = 1000,  # 检查间隔(毫秒)
    session = session,
    checkFunc = function() {
      # 封装检查逻辑,返回标识文件状态的值(比如修改时间)
      myFileCheck(file_csv)
    },
    valueFunc = function() {
      # 文件状态变化时执行读取逻辑
      myReadRoutine(file_csv)
    }
  )
  
  # 响应式数据处理:依赖df_shiny,数据更新时自动重新计算
  df_shiny_display = reactive({
    df_shiny() %>% mutate(val2 = val * 10)
  })
  
  # 渲染表格:依赖df_shiny_display,数据处理完成后自动更新
  output$my_data = renderTable(df_shiny_display())
}

shinyApp(ui = ui, server = server)
关键说明
  1. reactivePoll的正确用法:

    • checkFunc:无参函数,每隔指定间隔执行一次,返回能标识文件状态的值(如修改时间)。返回值变化时,触发valueFunc执行。
    • valueFunc:无参函数,文件状态变化时执行,返回最新读取的数据。
  2. 响应式逻辑对应场景:

    • reactive():用于创建有返回值的响应式对象,比如处理后的数据df_shiny_display,依赖的源数据更新时会自动重新计算。
    • observe/observeEvent:用于无返回值的副作用操作(如弹窗、写入文件),你的场景里不需要用到,仅用reactive()和输出渲染函数即可。
  3. 变量覆盖问题:
    原代码中先给df_shiny赋值为静态数据,后又用reactivePoll重新赋值,会导致逻辑混乱。修正后直接用reactivePoll创建响应式的df_shiny,启动时会自动执行一次读取逻辑获取初始数据。

内容的提问来源于stack exchange,提问作者mrroy

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.15 15:36:00