-2

我正在尝试使用 .exe 调用不在本地 Python 目录中的 .exe 文件subprocess.call()。该命令(当我将其键入 cmd.exe 时)完全如下:"C:\Program Files\R\R-2.15.2\bin\Rscript.exe" --vanilla C:\python\buyback_parse_guide.r

脚本运行,执行我需要做的事情,并且我确认输出是正确的。

这是我的python代码,我认为它会做同样的事情:

## Set Rcmd
Rcmd = r'"C:\Program Files\R\R-2.15.2\bin\Rscript.exe"'
## Set Rargs
Rargs = r'--vanilla C:\python\buyback_parse_guide.r'

retval = subprocess.call([Rcmd,Rargs],shell=True)

当我retval在 Python 控制台中调用时,它会返回1并且 .R 脚本没有运行,但我没有收到任何错误。我很确定这是一个非常简单的语法错误...帮助?非常感谢!

4

2 回答 2

1

引用文档

如果 shell 为 True,建议将 args 作为字符串而不是序列传递。

拆分它(手动或通过shlexsubprocess可以重新组合它们,以便外壳可以再次拆分它们是愚蠢的。

我不确定你为什么认为你需要shell=True这里。(如果你没有充分的理由,你通常不想要它......)但即使没有shell=True

在 Windows 上,如果 args 是一个序列,它将按照在 Windows 上将参数序列转换为字符串中描述的方式转换为字符串。这是因为底层的 CreateProcess() 对字符串进行操作。

所以,只需给 shell 命令行:

Rcmd = r'"C:\Program Files\R\R-2.15.2\bin\Rscript.exe" --vanilla C:\python\buyback_parse_guide.r'
retval = subprocess.call(Rcmd, shell=True)
于 2012-11-30T00:32:10.220 回答
0

根据文档,Rscript:

… 是 #! 中使用的替代前端 脚本和其他脚本应用程序。

……方便写#!脚本...(标准的 Windows 命令行没有 #! 脚本的概念,但 Cygwin shell 有。)

… 仅在具有 execv 系统调用的系统上受支持。

因此,这不是在 Windows 下从另一个程序运行 R 脚本的方法。

这个答案说:

Rscript.exe 是批处理脚本的好帮手……对于其他一切,还有 R.exe

因此,除非您有充分的理由在批处理脚本之外使用 Rscript,否则您应该切换到 R.exe。

您可能想知道为什么它可以在 cmd.exe 下工作,但不能在 Python 下工作。我不知道答案,我认为不值得通过代码挖掘或尝试找出答案,但我可以做出一些猜测。

一种可能性是,当您从命令行运行时,这是一个cmd.exe控制终端的 a,而当您从subprocess.call(shell=True)or运行时os.system,这是一个无头的cmd.exe. 运行 .bat/.cmd 批处理文件可以获得 non-headless cmd,但cmd直接从另一个应用程序运行不会。R 历来处理 Windows 终端的各种复杂性,这就是为什么他们曾经有单独的 Rterm.exe 和 Rcmd.exe 工具。如今,它们都合并到了 R.exe 中,无论哪种方式都应该可以正常工作。但是,如果您尝试做文档说不做的事情,那可能没有经过测试,它可能不起作用是完全合理的。

无论如何,即使它没有记录在案,为什么它在某些情况下有效并不重要。这当然并不意味着它应该在没有记录的其他情况下工作,或者你应该试图强迫它这样做。只需做正确的事情并运行R.exe而不是Rscript.exe.

除非您的某些信息与我在文档中找到的所有内容以及我能找到的所有其他内容相矛盾,否则我将把钱放在 Rscript.exe 本身就是问题所在。

您必须阅读有关 和 之间调用差异的文档Rscript.exeR.exe但它们并不相同。根据介绍文档,:

如果你只想运行一个文件 foo.R 的 R 命令,推荐的方法是使用 R CMD BATCH foo.R

根据您上面的评论:

当我在 cmd.exe 中键入 "C:\R\R-2.15.2\bin\i386\R.exe" CMD BATCH C:\python\buyback_parse_guide.r 时,.R 脚本运行成功。将它传递给 python 的正确语法是什么?

这取决于平台。在 Windows 上,参数列表会变成一个字符串,所以你最好只使用一个字符串,这样你就不必调试连接;在 Unix 上,一个字符串被分割成一个参数列表,所以你最好使用一个列表,这样你就不必调试连接。

由于路径中没有空格,我会去掉引号。

所以:

rcmd = r'C:\R\R-2.15.2\bin\i386\R.exe CMD BATCH C:\python\buyback_parse_guide.r'
retval = subprocess.call(rcmd)
于 2012-11-30T01:04:45.517 回答