管道子进程标准输出到变量

Ins*_*cal 88 python subprocess pipe python-2.6

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

def storels():
   a = subprocess.Popen("ls",shell=True)
storels()
Run Code Online (Sandbox Code Playgroud)

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

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

这也会将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
Run Code Online (Sandbox Code Playgroud)

mar*_*cog 125

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

>>> proc = subprocess.Popen('ls', stdout=subprocess.PIPE)
>>> output = proc.stdout.read()
>>> print output
bar
baz
foo
Run Code Online (Sandbox Code Playgroud)

该命令cdrecord --help输出到stderr,所以你需要管道那个indstead.您还应该将命令分解为令牌列表,如下所示,或者替代方法是传递shell=True参数但是这会激活一个完整的shell,如果您不控制其中的内容,这可能是危险的.命令字符串.

>>> 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 #.
...
Run Code Online (Sandbox Code Playgroud)

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

subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
Run Code Online (Sandbox Code Playgroud)

正如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 #.
...
Run Code Online (Sandbox Code Playgroud)

  • 在 Python3 下,`output` 不会是一个字符串,而是一个字节序列。尝试 `output.decode(encoding='utf-8')` 或 `output.decode(encoding='latin-1')` 来获取字符串。 (3认同)

ami*_*tas 30

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

output = subprocess.check_output('ls')
Run Code Online (Sandbox Code Playgroud)

要重定向stderr,您可以使用以下内容:

output = subprocess.check_output('ls', stderr=subprocess.STDOUT)
Run Code Online (Sandbox Code Playgroud)



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

output = subprocess.check_output(['ls', '-a'])
output = subprocess.check_output('ls -a', shell=True)
Run Code Online (Sandbox Code Playgroud)

  • 这不会按要求抑制输出(“我不希望将命令的输出打印到终端”)。 (2认同)

Chr*_*gan 11

有了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)
Run Code Online (Sandbox Code Playgroud)

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

proc = subprocess.Popen(['cdrecord', '--help'], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
stdout, stderr = proc.communicate()
Run Code Online (Sandbox Code Playgroud)


归档时间:

查看次数:

153591 次

最近记录:

11 年,4 月 前