subprocess.call的语法(Win7 x64)

时间:2012-11-30 00:18:44

标签: python r python-2.7 subprocess

我正在尝试使用subprocess.call()调用不在我的本地Python目录中的.exe文件。该命令(当我在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)

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

2 个答案:

答案 0 :(得分:1)

引用the docs

  

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

将其拆分(手动或通过shlex),subprocess可以将它们重新组合,以便shell再次拆分它们是愚蠢的。

我不确定您认为在这里需要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)

答案 1 :(得分:0)

根据the docs,Rscript:

  

...是用于#的另一种前端!脚本和其他脚本应用程序。

     

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

     

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

因此,它不是从Windows下的其他程序运行R脚本的方法。

This answer说:

  

Rscript.exe是批处理脚本的朋友......对于其他一切,都有R.exe

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

您可能想知道为什么它在cmd.exe下运行,但不是从Python运行。我不知道答案,我认为不值得深入挖掘代码或尝试查找,但我可以做出一些猜测。

一种可能性是,当您从命令行运行时,这是一个控制终端的cmd.exe,当您从subprocess.call(shell=True)os.system运行时,这是一个无头cmd.exe。运行.bat / .cmd批处理文件会使您无头cmd,但直接从其他应用运行cmd则不会。 R历史上有各种复杂性处理Windows终端,这就是他们过去使用单独的Rterm.exe和Rcmd.exe工具的原因。如今,这些都被合并到R.exe中,它应该可以正常工作。但是如果你尝试做文件说不做的事情,那可能没有经过测试,那么它可能不起作用是完全合理的。

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

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

您必须阅读有关Rscript.exeR.exe之间调用差异的文档,但它们并不完全相同。根据{{​​3}},:

  

如果您只想运行R命令的文件foo.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)