subprocess.Popen 的输出

Bre*_*ett 6 python subprocess

我一直在写一些 python 代码,在我的代码中我使用了“命令”

该代码按我的预期工作,但后来我在 Python 文档中注意到该命令已被弃用,并将在 Python 3 中删除,我应该改用“子进程”。

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

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

<subprocess.Popen object at 0xb7394c8c>
Run Code Online (Sandbox Code Playgroud)

我看到的所有例子都在那里,它似乎被接受,因为它总是在那里。

这段代码;

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

产生这个;

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

这是正常的吗?如果我将它用作将各种格式化详细信息输出到控制台的较大程序的一部分,它会将一切搞砸。

我正在使用该命令通过使用 ifconfig 以及各种 grep 和 awks 来获取接口的 IP 地址来抓取地址。

考虑这个代码;

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

这返回;

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

至少可以说这是模糊的。

显然我在这里遗漏了一些东西。我当然是 Python 的新手,所以我确定是我做错了,但到目前为止,各种谷歌搜索都没有结果。

如果我想要更干净的输出怎么办?我是否必须手动修剪有问题的输出,或者我是否错误地调用了 subprocess.Popen?

提前致谢!

nin*_*cko 5

“丑陋的字符串”是它应该打印的内容。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
...
Run Code Online (Sandbox Code Playgroud)

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

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

此外,您永远不想使用shell=True,因为它是一个安全漏洞(输入未消毒的主要安全漏洞,没有输入的次要安全漏洞,因为它允许通过修改 shell 环境进行本地攻击)。出于安全原因并避免错误,您通常希望传入一个列表而不是一个字符串。如果你很懒惰,你可以做 "ls -al".split(),这是不受欢迎的,但做类似 ("ls -l %s"%unsanitizedInput).split() 的事情会是一个安全漏洞。