Windows中的Python流水线子流程

Windows中的Python流水线子流程,python,subprocess,Python,Subprocess,我使用的是Windows7,我已经在Python2.6.6和Python3.2下试过了 因此,我尝试从Python调用此命令行: netstat -ano | find ":80" 在Windows cmd下,这一行工作得非常好 所以 第一次尝试: output = subprocess.Popen( [r'netstat -ano | find ":80"'], stdout=subprocess.PIPE, shell=T

我使用的是Windows7,我已经在Python2.6.6和Python3.2下试过了

因此,我尝试从Python调用此命令行:

netstat -ano | find ":80"
在Windows cmd下,这一行工作得非常好

所以

  • 第一次尝试:

    output = subprocess.Popen(
               [r'netstat -ano | find ":80"'],
               stdout=subprocess.PIPE,
               shell=True
    ).communicate()
    
    出现一个错误,“find”实际上没有收到正确的参数(例如“find”:80“\”):

  • 第二次尝试:

    #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.exe'、'-c']的子进程会导致类似死锁或空白cmd窗口的结果。我假设cmd会忽略'-c',导致communicate(),无限期地等待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”返回的字符串。这可能是一个bug吗?

我建议您在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连接处于活动状态):

在我看来,这更容易处理

请注意:

  • 选项shell=True不是必需的,但命令行窗口会快速打开和关闭。查看最适合您的选项,但注意命令注入
  • Popen参数列表应为字符串列表。不需要引用列表部分,子流程将为您处理
希望这有帮助


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

所以我重新审视了这个问题,并找到了两个解决方案(我前一段时间切换到了Python 2.7,所以我不确定Python 2.6,但应该是一样的。):

  • findstr替换find,并删除双引号

    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()
    

  • 这个问题产生于这样一个事实:['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]
      
      output = subprocess.Popen('echo find ":80"',
                                stdout=subprocess.PIPE,
                                shell=True)
                         .communicate()
      print output[0]
      
      返回:

      find \":80\"
      
      find ":80"
      
    • 运行:

      output = subprocess.Popen(['echo','find','":80"'],
                                stdout=subprocess.PIPE,
                                shell=True)
                         .communicate()
      print output[0]
      
      output = subprocess.Popen('echo find ":80"',
                                stdout=subprocess.PIPE,
                                shell=True)
                         .communicate()
      print output[0]
      
      返回:

      find \":80\"
      
      find ":80"
      

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

    • 管道操作符在子shell中执行以下命令;请参见(例如)

    • Python本身:

      请注意,(…)要在结果元组中获取除None之外的任何内容,还需要指定stdout=PIPE和/或stderr=PIPE


    不确定此“冲突”是否是一种bug,或者是一种设计选择。

    在尝试N1中,可能会起作用:
    ['cmd.exe'、'-c'、'netstat-ano | find':80']
    作为args数组。在这种情况下,还要删除
    shell=True
    @PavelRepin刚刚在Python2.6.6和Python3.2中都尝试过这一点。不幸的是,带有['cmd.exe','-c']的子进程会导致类似死锁或空白cmd窗口的结果…(已删除,移动到尝试3)抱歉@madeOfMeat,
    -c
    是我的一个难题。您尝试了
    /c
    ,这是正确的,尽管遗憾的是它仍然没有帮助。为什么不
    .Popen(['find',':80'],…)