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

时间:2022-03-01 15:48:36

I want to run a command in pythong, using the subprocess module, and store the output in a variable. However, I do not want the command's output to be printed to the terminal. For this code:

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

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

I get the directory listing in the terminal, instead of having it stored in a. I've also tried:

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

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

This also prints the output of ls to my terminal. I've even tried this command with the somewhat dated os.system method, since running ls > tmp in the terminal doesn't print ls to the terminal at all, but stores it in tmp. However, the same thing happens.

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

Edit:

编辑:

I get the following error after following marcog's advice, but only when running a more complex command. cdrecord --help. Python spits this out:

遵循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

3 个解决方案

#1


111  

To get the output of ls, use stdout=subprocess.PIPE.

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

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

The command cdrecord --help outputs to stderr, so you need to pipe that indstead. You should also break up the command into a list of tokens as I've done below, or the alternative is to pass the shell=True argument but this fires up a fully-blown shell which can be dangerous if you don't control the contents of the command string.

命令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 #.
...

If you have a command that outputs to both stdout and stderr and you want to merge them, you can do that by piping stderr to stdout and then catching stdout.

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

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

As mentioned by Chris Morgan, you should be using proc.communicate() instead of proc.read().

正如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 #.
...

#2


23  

If you are using python 2.7 or later, the easiest way to do this is to use the subprocess.check_output() command. Here is an example:

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

output = subprocess.check_output('ls')

To also redirect stderr you can use the following:

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

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



In the case that you want to pass parameters to the command, you can either use a list or use invoke a shell and use a single string.

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

output = subprocess.check_output(['ls', '-a'])
output = subprocess.check_output('ls -a', shell=True)

#3


10  

With a = subprocess.Popen("cdrecord --help",stdout = subprocess.PIPE) , you need to either use a list or use shell=True;

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

Either of these will work. The former is preferable.

这些都可以。前者是优选的。

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

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

Also, instead of using Popen.stdout.read/Popen.stderr.read, you should use .communicate() (refer to the subprocess documentation for why).

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

proc = subprocess.Popen(['cdrecord', '--help'], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
stdout, stderr = proc.communicate()

#1


111  

To get the output of ls, use stdout=subprocess.PIPE.

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

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

The command cdrecord --help outputs to stderr, so you need to pipe that indstead. You should also break up the command into a list of tokens as I've done below, or the alternative is to pass the shell=True argument but this fires up a fully-blown shell which can be dangerous if you don't control the contents of the command string.

命令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 #.
...

If you have a command that outputs to both stdout and stderr and you want to merge them, you can do that by piping stderr to stdout and then catching stdout.

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

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

As mentioned by Chris Morgan, you should be using proc.communicate() instead of proc.read().

正如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 #.
...

#2


23  

If you are using python 2.7 or later, the easiest way to do this is to use the subprocess.check_output() command. Here is an example:

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

output = subprocess.check_output('ls')

To also redirect stderr you can use the following:

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

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



In the case that you want to pass parameters to the command, you can either use a list or use invoke a shell and use a single string.

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

output = subprocess.check_output(['ls', '-a'])
output = subprocess.check_output('ls -a', shell=True)

#3


10  

With a = subprocess.Popen("cdrecord --help",stdout = subprocess.PIPE) , you need to either use a list or use shell=True;

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

Either of these will work. The former is preferable.

这些都可以。前者是优选的。

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

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

Also, instead of using Popen.stdout.read/Popen.stderr.read, you should use .communicate() (refer to the subprocess documentation for why).

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

proc = subprocess.Popen(['cdrecord', '--help'], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
stdout, stderr = proc.communicate()