如何在Quarto中正确渲染含Python input()的用户输入代码?
Python input()函数在Quarto文档渲染中的问题解决
问题场景与报错
我在RStudio里渲染Quarto文档,用来演示Python的input()函数功能。之前用Jupyter引擎跑Python代码出了问题,换成reticulate搭配knitr引擎。文档里的Python代码块没有用户输入时能正常渲染,但包含以下内容的.qmd文档渲染失败:
def get_input(): x = input("give me an input: ") print("Your input is ", "\"" + str(x) + "\"") get_input() Hello world. # <-- 用户输入 get_input() 23 # <-- 用户输入
渲染时报错:
Quitting from lines 8-17 (test.qmd) Error: invalid syntax (<string>, line 6) Execution halted
这个语法错误指向代码块第6行(也就是“Hello world.”那行用户输入),但在RStudio里直接运行这个代码块是能正常输出结果的。我有两个问题:
- 是否有其他方式放置用户输入值,避免渲染问题?
- 使用非knitr的其他引擎能不能解决这个问题?
我的YAML头如下:
--- title: "test" author: "mattrex" format: html engine: knitr ---
问题解答
问题1:替代的用户输入处理方式
因为Quarto渲染文档是批量执行代码,无法像交互式环境那样实时接收用户输入,所以需要预先模拟输入内容:
- 模拟输入流:利用Python的
sys.stdin预先注入所有需要的输入内容,按调用顺序排列:import sys from io import StringIO # 按两次input()的顺序设置输入内容,用换行分隔 sys.stdin = StringIO("Hello world.\n23\n") def get_input(): x = input("give me an input: ") print("Your input is ", "\"" + str(x) + "\"") get_input() get_input() - 分块隐藏模拟代码:如果需要保留原演示代码的展示效果,可以把模拟输入的代码单独放在一个隐藏的代码块里:
#| echo: false import sys from io import StringIO sys.stdin = StringIO("Hello world.\n23\n")
这样渲染时会正常执行逻辑,同时展示的是原演示代码。def get_input(): x = input("give me an input: ") print("Your input is ", "\"" + str(x) + "\"") get_input() get_input()
问题2:更换引擎的可行性
- Jupyter引擎:若之前用Jupyter引擎的问题是配置导致,可以尝试重新调整。在YAML头中设置
engine: jupyter,确保RStudio能识别正确的Python Jupyter内核。Jupyter引擎对交互式输入的模拟兼容性更好,也可以用上述的输入流模拟方式来处理。 - Python原生引擎:直接在YAML头设置
engine: python,脱离R的reticulate依赖。这种情况下同样可以用sys.stdin模拟输入,直接调用Python解释器执行代码,避免R层的兼容问题。
内容的提问来源于stack exchange,提问作者mattxrex
相关产品推荐
相关产品推荐

