如何在Python中使用subprocess.check_output()?


72

我找到了有关subprocess.check_output()的文档,但是找不到带有参数的文档,而且该文档也不是很深入。我正在使用Python 3(但试图通过Python 3运行Python 2文件)

我正在尝试运行以下命令: python py2.py -i test.txt

-i是argparse的位置参数,test.txt是-i,py2.py是要运行的文件

我尝试了很多(无效)变体,包括: py2output = subprocess.check_output([str('python py2.py '),'-i', 'test.txt'])

py2output = subprocess.check_output([str('python'),'py2.py','-i', test.txt'])


1
他们不工作时到底发生了什么?
khagler

1
试图通过Python 3运行Python 2文件?不,不会发生。Python 3中故意使用Python 2.不向后兼容你必须运行2to3初学者,让您的档案工作在Python 3

1
@Makoto:他正在尝试从Python 3脚本中运行Python 2解释器,这是完全合理的。(并且从他之前的问题中得知,他是专门为解决您正在考虑的问题而专门设计的,但这与此处无关。)
abarnert 2012年

向我们展示您的py2.py脚本,输出的内容以及最终在py2output中输出的内容(假设它返回而不是引发)。
abarnert

1
另外,关于Python 2的全部内容以及关于您希望py2.py如何解释参数的问题都与该问题无关。它使至少一个人(Makoto)感到困惑,否则他们可能会给您一个很好的答案,也可能使其他人感到困惑或恐惧。将来,如果您能提供一个最小的示例,而不会引起不必要的干扰,那么您可能会得到更好的答案。
abarnert

Answers:


76

正确的答案(使用Python 2.7及更高版本,因为那时check_output() 引入)是:

py2output = subprocess.check_output(['python','py2.py','-i', 'test.txt'])

为了演示,这是我的两个程序:

py2.py:

import sys
print sys.argv

py3.py:

import subprocess
py2output = subprocess.check_output(['python', 'py2.py', '-i', 'test.txt'])
print('py2 said:', py2output)

运行它:

$ python3 py3.py
py2 said: b"['py2.py', '-i', 'test.txt']\n"

这是每个版本的问题所在:

py2output = subprocess.check_output([str('python py2.py '),'-i', 'test.txt'])

首先,str('python py2.py')与—完全相同,您'python py2.py'要使用str,然后调用str将其转换为str。这使代码更难阅读,更长,甚至更慢,而没有任何好处。

更严重的是,python py2.py不能将其作为一个参数,除非您实际上正在尝试运行名为的程序/usr/bin/python\ py2.py。你不是 例如,您尝试/usr/bin/python使用第一个参数运行py2.py。因此,您需要使它们成为列表中单独的元素。

您的第二个版本已解决此问题,但您没有找到'以前的版本test.txt'。这可能会给你一个SyntaxError大概的答案EOL while scanning string literal

同时,我不确定您是如何找到文档的,但是找不到带有参数的示例。第一个示例是:

>>> subprocess.check_output(["echo", "Hello World!"])
b'Hello World!\n'

这会调用"echo"带有附加参数的命令"Hello World!"

也:

-i是argparse的位置参数,test.txt是-i是

我敢肯定-i不是一个位置参数,但一个可选的参数。否则,句子的后半部分是没有意义的。


现在我在argparse中尝试了2个参数。我试图将这个命令放入子过程:python py2.py -i test.txt -l ong我根据您的回答尝试了这个子过程:py2output=subprocess.check_output(["python","py2.py","-i","test.txt","-l","ong"])但是它不起作用。
JOHANNES_NYÅTT

2
@ user1925847:“不起作用”是什么意思?这不是有用的评论。如果您做对了,它就会奏效-正如我的答案所示。因此,显然您做错了。但是不可能猜测。正如我在对一个主要问题的评论中所说的那样:向我们展示您的脚本,并告诉我们预期的和实际的输出是什么,或者没有希望猜测您在做什么错。
abarnert 2012

1
并且不要忘记捕获CalledProcessErrorOSError异常。
anatoly techtonik

1
我建议使用函数shlex.split(“ python py2.py -i test.txt”)将字符串拆分为参数列表。
compie

问题:怎么subprocess.check_output(['cd', 'C:\'])不起作用?我收到“ FileNotFoundError:[WinError 2]系统找不到指定的文件”。
阿德里安·凯斯特

12

添加到@abarnert提到的内容

更好的是捕捉异常

import subprocess
try:
    py2output = subprocess.check_output(['python', 'py2.py', '-i', 'test.txt'],stderr= subprocess.STDOUT)  
    #print('py2 said:', py2output)
    print "here"
except subprocess.CalledProcessError as e:
    print "Calledprocerr"

这个stderr = subprocess.STDOUT是为了确保您不会在stderr中收到filenotfound错误-通常无法在filenotfoundexception中捕获该错误,否则最终会得到

python: can't open file 'py2.py': [Errno 2] No such file or directory

实际上,一个更好的解决方案可能是检查文件/脚本是否存在,然后运行文件/脚本


12

因为Python 3.5,subprocess.run()建议在subprocess.check_output()

>>> subprocess.run(['cat','/tmp/text.txt'], stdout=subprocess.PIPE).stdout
b'First line\nSecond line\n'

从Python 3.7开始,您可以使用capture_output=true参数来捕获stdout和stderr而不是上面的代码:

>>> subprocess.run(['cat','/tmp/text.txt'], capture_output=True).stdout
b'First line\nSecond line\n'

另外,您可能要使用universal_newlines=TruePython 3.7或更高版本的text=True文本,而不是二进制文件:

>>> stdout = subprocess.run(['cat', '/tmp/text.txt'], capture_output=True, text=True).stdout
>>> print(stdout)
First line
Second line

有关更多信息,请参见subprocess.run()文档。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.