Python - 在Windows中流水线化子流程

时间:2011-06-14 02:32:04

标签: python subprocess

我正在使用Windows 7,我在Python 2.6.6和Python 3.2下尝试过这个。

所以我试图从Python调用这个命令行:

netstat -ano | find ":80"

在Windows cmd下,此行完全正常。

所以,

  • 第一次尝试:

    output = subprocess.Popen(
               [r'netstat -ano | find ":80"'],
               stdout=subprocess.PIPE,
               shell=True
    ).communicate()
    

    引发错误,“发现”实际上没有收到正确的参数(例如'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 - \
    

我做错了什么? :(

编辑:

  • 第3次尝试(如@Pavel Repin建议的那样):

    cmd_netstat = subprocess.Popen(
                    ['cmd.exe', '-c', 'netstat -ano | find ":80"'],
                    stdout=subprocess.PIPE
    ).communicate()
    

    不幸的是,使用['cmd.exe',' - c']的子进程导致类似死锁或空白cmd窗口的内容。我假设cmd忽略'-c',导致communic()无限期地等待cmd终止。由于这是Windows,我的赌注是cmd只接受以斜杠(/)开头的参数。所以我用'/ c'代替'-c':

    cmd_netstat = subprocess.Popen(
                    ['cmd.exe', '/c', 'netstat -ano | find ":80"'],
                    stdout=subprocess.PIPE
    ).communicate()
    

    然后......回到同样的错误:

    Access denied - \
    

编辑: 我放弃了,我将只处理Python中'netstat -ano'返回的字符串。这可能是个错误吗?

3 个答案:

答案 0 :(得分:3)

所以我重新回答了这个问题,发现了两个解决方案(我之前转向Python 2.7,所以我不确定Python 2.6,但它应该是相同的。):

  1. find 替换为 findstr ,并删除双引号

    output = subprocess.Popen(['netstat','-ano','|','findstr',':80'],
                              stdout=subprocess.PIPE,
                              shell=True)
                       .communicate()
    

    但这并不能解释为什么“查找”无法使用,所以:

  2. 使用字符串参数代替列表

    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()
    
  3. 问题来自于:['find','“:80”']实际上被翻译成['find,'\“:80 \”']。 因此,在Windows命令shell中执行以下命令:

    >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"
      

答案 1 :(得分:2)

我建议您在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']

在我看来,这更容易使用。

请注意:

  • option shell = True不是必需的,但命令行窗口会快速打开 - 关闭。看看最适合你的是什么,但要注意命令注入;
  • Popen参数列表应为字符串列表。不需要引用列表部分,子流程将为您处理。

希望这有帮助。

编辑:哎呀,我错过了编辑的最后一行。看起来你已经有了自己的想法。

答案 2 :(得分:0)

再次阅读这个旧问题后的新答案:这可能是由于以下两个事实:

不确定这种“冲突”是错误还是设计选择。