subprocess.Popen的输出

时间:2011-05-27 02:21:58

标签: python subprocess

我一直在编写一些python代码,在我的代码中我正在使用"命令"

代码按照我的意图工作,但后来我在Python文档中注意到该命令已被弃用,将在Python 3中删除,我应该使用" subprocess"代替。

" OK"我想,"我不希望我的代码直接进入遗留状态,所以我现在应该改变它。

问题是subprocess.Popen似乎在任何输出的开头添加一个令人讨厌的字符串,例如

<subprocess.Popen object at 0xb7394c8c>

我看到的所有例子都有它,它似乎被接受,因为它始终存在。

此代码;

#!/usr/bin/python
import subprocess
output = subprocess.Popen("ls -al", shell=True)
print output

产生这个;

<subprocess.Popen object at 0xb734b26c>
brettg@underworld:~/dev$ total 52
drwxr-xr-x  3 brettg brettg 4096 2011-05-27 12:38 .
drwxr-xr-x 21 brettg brettg 4096 2011-05-24 17:40 ..
<trunc>

这是正常的吗?如果我将它用作一个较大的程序的一部分,该程序将各种格式化的细节输出到控制台,它就会混乱一切。

我使用该命令获取接口的IP地址,方法是使用ifconfig以及各种greps和awks来获取地址。

考虑这段代码;

#!/usr/bin/python
import commands,subprocess

def new_get_ip (netif):
address = subprocess.Popen("/sbin/ifconfig " + netif + " | grep inet | grep -v inet6 | awk '{print $2}' | sed 's/addr://'i", shell=True)
return address

def old_get_ip (netif):
address = commands.getoutput("/sbin/ifconfig " + netif + " | grep inet | grep -v inet6 | awk '{print $2}' | sed 's/addr://'i")
return address

print "OLD IP is :",old_get_ip("eth0")
print ""
print "NEW IP is :",new_get_ip("eth0")

返回;

brettg@underworld:~/dev$ ./IPAddress.py
OLD IP is : 10.48.16.60

NEW IP is : <subprocess.Popen object at 0xb744270c>
brettg@underworld:~/dev$ 10.48.16.60

至少可以说这很难。

显然我在这里遗漏了一些东西。我当然是Python新手,所以我确定这是我做错了事,但各种谷歌搜索在这一点上毫无结果。

如果我想要清洁输出怎么办?我是否必须手动修剪有问题的输出或我是否正在调用subprocess.Popen?

提前致谢!

3 个答案:

答案 0 :(得分:4)

“丑陋的字符串”应该打印的内容。 Python正确地打印出repr(subprocess.Popen(...)),就像你说print(open('myfile.txt'))时打印的那样。

此外,python不知道输出到stdout的内容。您看到的输出是来自python的,但是从进程的stdout和stderr被重定向到您的终端作为垃圾邮件,甚至没有通过python进程。这就像你运行程序someprogram &而没有将其stdout和stderr重定向到/dev/null,然后尝试运行另一个命令,但你偶尔会看到程序中的垃圾邮件。重复和澄清:

<subprocess.Popen object at 0xb734b26c>  <-- output of python program
brettg@underworld:~/dev$ total 52                     <-- spam from your shell, not from python
drwxr-xr-x  3 brettg brettg 4096 2011-05-27 12:38 .   <-- spam from your shell, not from python
drwxr-xr-x 21 brettg brettg 4096 2011-05-24 17:40 ..  <-- spam from your shell, not from python
...

为了捕获标准输出,你必须使用.communicate()函数,如下所示:

#!/usr/bin/python
import subprocess
output = subprocess.Popen(["ls", "-a", "-l"], stdout=subprocess.PIPE).communicate()[0]
print output

此外,您永远不想使用shell=True,因为它是一个安全漏洞(一个主要的安全漏洞,带有未经过输入的输入,一个没有输入的次要漏洞,因为它通过修改shell环境允许本地攻击)。出于安全原因以及避免错误,您通常希望传入列表而不是字符串。如果你很懒,你可以做“ls -al”.split(),这是不赞成的,但是做一些像(“ls -l%s”%unsanitizedInput).split()这样的安全漏洞。

答案 1 :(得分:0)

有关更多信息,请参见subprocess module documentation

以下是使用子进程模块从程序获取stdout和stderr的方法:

from subprocess import Popen, PIPE, STDOUT

cmd = 'echo Hello World'
p = Popen(cmd, shell=True, stdin=PIPE, stdout=PIPE, stderr=STDOUT, close_fds=True)
output = p.stdout.read()
print output

结果:

b'Hello\r\n'

您可以使用PowerShell运行命令并查看结果:

from subprocess import Popen, PIPE, STDOUT
cmd = 'powershell.exe ls'
p = Popen(cmd, shell=True, stdin=PIPE, stdout=PIPE, stderr=STDOUT, close_fds=True)
output = p.stdout.read()

useful link

答案 2 :(得分:0)

变量output不包含字符串,它是subprocess.Popen()函数的容器。您不需要打印它。代码

import subprocess
output = subprocess.Popen("ls -al", shell=True)

完美运行,但没有打印出丑陋的<subprocess.Popen object at 0xb734b26c>