在Shiny应用中使用reticulate调用Python脚本时变量传递失败求助
问题:Shiny应用调用Python脚本无法识别R反应式变量
想要创建Shiny应用,在应用内调用Python脚本并传入textInput定义的year变量,但Python脚本无法识别该R变量,运行时报错。
Shiny应用代码
library(shiny) library(reticulate) # Define the user interface ui <- fluidPage( tabsetPanel( tabPanel(textInput("year", "Year"), downloadButton("download_btn", "Download")) ) ) server <- function(input, output, session) { year <- reactive(input$year) adjusted_data <- reactive({ source_python("python_script.py") data <- read_csv("tmp.csv") data }) output$download_btn <- downloadHandler( filename = function() { file_name <- "temp.xlsx" }, content = function(file) { openxlsx::write.xlsx(adjusted_data(), file) } ) } shinyApp(ui, server)
Python脚本(python_script.py)
year = r.year()
报错信息
Listening on http://127.0.0.1:7564
Warning: Error in eval: RuntimeError: object 'year' not found
Runreticulate::py_last_error()for details.
4: runApp
3: print.shiny.appobj
1: source
错误原因
year是Shiny的反应式变量,仅存在于Shiny的反应式上下文环境中,不是R全局环境中的普通变量,Python脚本通过r.year()无法直接访问。source_python执行时,Python无法感知Shiny的反应式环境,自然找不到名为year的R对象。
解决方法
方法1:用Python函数接收参数(推荐)
把Python脚本改成函数形式,在R中调用函数时传入反应式变量的值,这是最规范的交互方式。
修改Python脚本
import pandas as pd def process_year(year): # 这里替换成你的实际处理逻辑,示例生成包含年份的CSV df = pd.DataFrame({"Year": [year]}) df.to_csv("tmp.csv", index=False)
修改Shiny的server部分
server <- function(input, output, session) { year <- reactive(input$year) adjusted_data <- reactive({ # 加载Python函数 source_python("python_script.py") # 调用Python函数,注意加括号获取反应式变量的当前值 process_year(year()) # 读取生成的文件 data <- readr::read_csv("tmp.csv") data }) output$download_btn <- downloadHandler( filename = function() { "temp.xlsx" }, content = function(file) { openxlsx::write.xlsx(adjusted_data(), file) } ) }
方法2:将变量存入R全局环境
如果坚持要在Python脚本中直接访问R变量,可以先把反应式变量的值赋值到R全局环境,再执行Python脚本。
修改Shiny的server部分
adjusted_data <- reactive({ # 将反应式变量的值存入全局环境 assign("year_val", year(), envir = .GlobalEnv) # 执行Python脚本 source_python("python_script.py") data <- readr::read_csv("tmp.csv") data })
修改Python脚本
import pandas as pd # 访问R全局环境中的year_val变量 year = r.year_val # 替换成你的实际处理逻辑 df = pd.DataFrame({"Year": [year]}) df.to_csv("tmp.csv", index=False)
内容的提问来源于stack exchange,提问作者Theki
相关产品推荐
相关产品推荐

