106

我想pythong使用 subprocess 模块在 中运行命令,并将输出存储在变量中。但是,我不希望将命令的输出打印到终端。对于此代码:

def storels():
   a = subprocess.Popen("ls",shell=True)
storels()

我在终端中获取目录列表,而不是将其存储在a. 我也试过:

 def storels():
       subprocess.Popen("ls > tmp",shell=True)
       a = open("./tmp")
       [Rest of Code]
 storels()

这也将 ls 的输出打印到我的终端。我什至用有点过时的 os.system 方法尝试了这个命令,因为ls > tmp在终端中运行根本不会打印ls到终端,而是将其存储在tmp. 然而,同样的事情也会发生。

编辑:

遵循 marcog 的建议后,我收到以下错误,但仅在运行更复杂的命令时。cdrecord --help. Python 吐出这个:

Traceback (most recent call last):
  File "./install.py", line 52, in <module>
    burntrack2("hi")
  File "./install.py", line 46, in burntrack2
    a = subprocess.Popen("cdrecord --help",stdout = subprocess.PIPE)
  File "/usr/lib/python2.6/subprocess.py", line 633, in __init__
    errread, errwrite)
  File "/usr/lib/python2.6/subprocess.py", line 1139, in _execute_child
    raise child_exception
OSError: [Errno 2] No such file or directory
4

3 回答 3

151

要获得 的输出ls,请使用stdout=subprocess.PIPE

>>> proc = subprocess.Popen('ls', stdout=subprocess.PIPE)
>>> output = proc.stdout.read()
>>> print output
bar
baz
foo

该命令cdrecord --help输出到 stderr,因此您需要通过管道来代替。您还应该像我在下面所做的那样将命令分解为令牌列表,或者另一种方法是传递shell=True参数,但这会启动一个成熟的外壳,如果您不控制的内容可能会很危险命令字符串。

>>> proc = subprocess.Popen(['cdrecord', '--help'], stderr=subprocess.PIPE)
>>> output = proc.stderr.read()
>>> print output
Usage: wodim [options] track1...trackn
Options:
    -version    print version information and exit
    dev=target  SCSI target to use as CD/DVD-Recorder
    gracetime=# set the grace time before starting to write to #.
...

如果您有一个同时输出到 stdout 和 stderr 的命令并且想要合并它们,您可以通过将 stderr 管道传输到 stdout 然后捕获 stdout 来实现。

subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)

正如Chris Morgan所提到的,您应该使用proc.communicate()而不是proc.read().

>>> proc = subprocess.Popen(['cdrecord', '--help'], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
>>> out, err = proc.communicate()
>>> print 'stdout:', out
stdout: 
>>> print 'stderr:', err
stderr:Usage: wodim [options] track1...trackn
Options:
    -version    print version information and exit
    dev=target  SCSI target to use as CD/DVD-Recorder
    gracetime=# set the grace time before starting to write to #.
...
于 2010-12-22T23:49:40.080 回答
42

如果您使用的是 python 2.7 或更高版本,最简单的方法是使用subprocess.check_output()命令。这是一个例子:

output = subprocess.check_output('ls')

要重定向 stderr,您可以使用以下命令:

output = subprocess.check_output('ls', stderr=subprocess.STDOUT)



如果要将参数传递给命令,可以使用列表或调用 shell 并使用单个字符串。

output = subprocess.check_output(['ls', '-a'])
output = subprocess.check_output('ls -a', shell=True)
于 2012-03-16T18:25:21.017 回答
13

使用a = subprocess.Popen("cdrecord --help",stdout = subprocess.PIPE) ,您需要使用列表或使用shell=True;

这些中的任何一个都可以。前者更可取。

a = subprocess.Popen(['cdrecord', '--help'], stdout=subprocess.PIPE)

a = subprocess.Popen('cdrecord --help', shell=True, stdout=subprocess.PIPE)

此外,您应该使用而不是使用Popen.stdout.read/ (请参阅子流程文档了解原因)。Popen.stderr.read.communicate()

proc = subprocess.Popen(['cdrecord', '--help'], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
stdout, stderr = proc.communicate()
于 2010-12-23T00:17:05.203 回答