subprocess.Popen 的输出 [英] Output from subprocess.Popen

查看:89
本文介绍了subprocess.Popen 的输出的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I've been writing some python code and in my code I was using "command"

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

The code was working as I intended but then I noticed in the Python docs that command has been deprecated and will be removed in Python 3 and that I should use "subprocess" instead.

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

"OK" I think, "I don't want my code to go straight to legacy status, so I should change that right now.

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

The thing is that subprocess.Popen seems to prepend a nasty string to the start of any output e.g.

<subprocess.Popen object at 0xb7394c8c>

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

All the examples I see have it there, it seems to be accepted as given that it is always there.

这段代码;

#!/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>

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

Is this normal? If I use it as part of a larger program that outputs various formatted details to the console it messes everything up.

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

I'm using the command to obtain the IP address for an interface by using ifconfig along with various greps and awks to scrape the address.

考虑这个代码;

#!/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 新手,所以我确定是我做错了,但到目前为止,各种谷歌搜索都没有结果.

Obviously I am missing something here. I am new to Python of course so I'm sure it is me doing the wrong thing but various google searches have been fruitless to this point.

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

What if I want cleaner output? Do I have to manually trim the offending output or am I invoking subprocess.Popen incorrectly?

提前致谢!

推荐答案

丑陋的字符串"应该打印的内容.Python 正确地打印出 repr(subprocess.Popen(...)),就像如果你说 print(open('myfile.txt')) 它将打印出来的一样代码>.

The "ugly string" is what it should be printing. Python is correctly printing out the repr(subprocess.Popen(...)), just like what it would print if you said print(open('myfile.txt')).

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

Furthermore, python has no knowledge of what is being output to stdout. The output you are seeing is not from python, but from the process's stdout and stderr being redirected to your terminal as spam, that is not even going through the python process. It's like you ran a program someprogram & without redirecting its stdout and stderr to /dev/null, and then tried to run another command, but you'd occasionally see spam from the program. To repeat and clarify:

<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() 函数,如下所示:

In order to capture stdout, you must use the .communicate() function, like so:

#!/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() 的事情会是一个安全漏洞.

Furthermore, you never want to use shell=True, as it is a security hole (a major security hole with unsanitized inputs, a minor one with no input because it allows local attacks by modifying the shell environment). For security reasons and also to avoid bugs, you generally want to pass in a list rather than a string. If you're lazy you can do "ls -al".split(), which is frowned upon, but it would be a security hole to do something like ("ls -l %s"%unsanitizedInput).split().

这篇关于subprocess.Popen 的输出的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆