Python - 在Windows中管道子进程
我在用Windows 7,尝试过Python 2.6.6和Python 3.2。
我想从Python里调用这个命令行:
netstat -ano | find ":80"
在Windows的命令提示符下,这行命令运行得很好。
所以,
第一次尝试:
output = subprocess.Popen( [r'netstat -ano | find ":80"'], stdout=subprocess.PIPE, shell=True ).communicate()
出现了一个错误,提示'find'没有收到正确的参数(比如'find ":80" \'):
Access denied - \
第二次尝试:
#calling netstat cmd_netstat = subprocess.Popen( ['netstat','-ano'], stdout = subprocess.PIPE ) #pipelining netstat result into find cmd_find = subprocess.Popen( ['find','":80"'], stdin = cmd_netstat.stdout, stdout = subprocess.PIPE )
同样的错误又出现了。
Access denied - \
我到底做错了什么呢? :(
编辑:
第三次尝试(根据@Pavel Repin的建议):
cmd_netstat = subprocess.Popen( ['cmd.exe', '-c', 'netstat -ano | find ":80"'], stdout=subprocess.PIPE ).communicate()
不幸的是,用['cmd.exe','-c']的子进程结果像是死锁或者出现了一个空的命令窗口。我猜'-c'被命令提示符忽略了,导致communicate()一直在等命令提示符结束。因为这是Windows,我认为命令提示符只接受以斜杠(/)开头的参数。所以我把'-c'换成了'/c':
cmd_netstat = subprocess.Popen( ['cmd.exe', '/c', 'netstat -ano | find ":80"'], stdout=subprocess.PIPE ).communicate()
结果……又回到了同样的错误:
Access denied - \
编辑: 我放弃了,我决定在Python里处理'netstat -ano'返回的字符串。这可能是个bug吗?
3 个回答
3
我建议你在Python代码中尽量多做事情。你可以执行以下命令:
# executing the command
import subprocess
output = subprocess.Popen(['netstat', '-ano'], stdout=subprocess.PIPE).communicate()
然后通过解析输出结果:
# filtering the output
valid_lines = [ line for line in output[0].split('\r\n') if ':80' in line ]
你会得到一系列的行。在我的电脑上,端口号1900的输出看起来是这样的(没有激活html连接):
[' UDP 127.0.0.1:1900 *:* 1388', ' UDP 192.xxx.xxx.233:1900 *:* 1388']
我觉得这样处理起来更简单。
注意:
- 选项shell=True不是必须的,但会快速打开和关闭一个命令行窗口。看看哪个更适合你,但要注意命令注入的问题;
- Popen的参数列表应该是一个字符串列表。列表中的部分不需要加引号,subprocess会帮你处理这些。
希望这对你有帮助。
编辑:哎呀,我漏掉了最后一行的编辑。看起来你已经自己想明白了。
3
我重新看了一下这个问题,发现了两个解决方案(我之前换到了Python 2.7,所以对Python 2.6不太确定,但应该是一样的):
把find换成findstr,并去掉双引号
output = subprocess.Popen(['netstat','-ano','|','findstr',':80'], stdout=subprocess.PIPE, shell=True) .communicate()
不过这并没有解释为什么不能用"find",所以:
用字符串参数代替列表
output = subprocess.Popen('netstat -ano | find ":80"', stdout=subprocess.PIPE, shell=True) .communicate()
或者
pipeout = subprocess.Popen(['netstat', '-ano'], stdout = subprocess.PIPE) output = subprocess.Popen('find ":80"', stdin = pipeout.stdout, stdout = subprocess.PIPE) .communicate()
问题出在:['find','":80"']实际上被转换成了['find,'\":80\"']。
因此在Windows命令行中执行的命令是:>find \":80\"
Access denied - \
证明:
运行:
output = subprocess.Popen(['echo','find','":80"'], stdout=subprocess.PIPE, shell=True) .communicate() print output[0]
返回:
find \":80\"
运行:
output = subprocess.Popen('echo find ":80"', stdout=subprocess.PIPE, shell=True) .communicate() print output[0]
返回:
find ":80"