【问题标题】:How to get output from external command combine with Pipe如何从外部命令中获取输出与管道相结合
【发布时间】:2009-09-10 11:17:53
【问题描述】:

我有这样的命令。

wmctrl -lp | awk '/gedit/ { print $1 }'

我想要它在 python 脚本中的输出,我试过这段代码

>>> import subprocess
>>> proc =  subprocess.Popen(["wmctrl -lp", "|","awk '/gedit/ {print $1}"], shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
>>> proc.stdout.readline()
'0x0160001b -1 6504   beer-laptop x-nautilus-desktop\n'
>>> proc.stdout.readline()
'0x0352f117  0 6963   beer-laptop How to get output from external command combine with Pipe - Stack Overflow - Chromium\n'
>>> proc.stdout.readline()
'0x01400003 -1 6503   beer-laptop Bottom Expanded Edge Panel\n'
>>> 

看来我的代码是错误的,只有 wmctrl -lp 被执行,| awk '{print $1}' 被省略 我的预期输出是0x03800081

$ wmctrl -lp | awk '/gedit/ {print $1}'
0x03800081

请帮忙。

【问题讨论】:

    标签: python linux pipe


    【解决方案1】:

    对于shell=True,您应该使用单个命令行而不是数组,否则您的附加参数将被解释为 shell 参数。来自subprocess documentation

    在 Unix 上,shell=True:如果 args 是字符串,它指定要通过 shell 执行的命令字符串。如果 args 是一个序列,第一项指定命令字符串,任何附加项都将被视为附加的 shell 参数。

    所以你的电话应该是:

    subprocess.Popen("wmctrl -lp | sed /gedit/ '{print $1}'", shell=True, ...
    

    我想你可能还有一个不平衡的单引号。

    【讨论】:

      【解决方案2】:

      因为您正在为程序传递一个序列,所以它认为管道是wmcrtrl 的一个参数,比如如果你这样做了

      wmctrl -lp "|"
      

      因此实际的管道操作丢失了。

      将其设为单个字符串确实应该会给您正确的结果:

      >>> import subprocess as s
      >>> proc = s.Popen("echo hello | grep e", shell=True, stdout=s.PIPE, stderr=s.PIPE)
      >>> proc.stdout.readline()
      'hello\n'
      >>> proc.stdout.readline()
      ''
      

      【讨论】:

        【解决方案3】:

        经过一些研究,我有以下代码对我来说非常有效。它基本上实时打印标准输出和标准错误。希望它可以帮助其他需要它的人。

        stdout_result = 1
        stderr_result = 1
        
        
        def stdout_thread(pipe):
            global stdout_result
            while True:
                out = pipe.stdout.read(1)
                stdout_result = pipe.poll()
                if out == '' and stdout_result is not None:
                    break
        
                if out != '':
                    sys.stdout.write(out)
                    sys.stdout.flush()
        
        
        def stderr_thread(pipe):
            global stderr_result
            while True:
                err = pipe.stderr.read(1)
                stderr_result = pipe.poll()
                if err == '' and stderr_result is not None:
                    break
        
                if err != '':
                    sys.stdout.write(err)
                    sys.stdout.flush()
        
        
        def exec_command(command, cwd=None):
            if cwd is not None:
                print '[' + ' '.join(command) + '] in ' + cwd
            else:
                print '[' + ' '.join(command) + ']'
        
            p = subprocess.Popen(
                command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, cwd=cwd
            )
        
            out_thread = threading.Thread(name='stdout_thread', target=stdout_thread, args=(p,))
            err_thread = threading.Thread(name='stderr_thread', target=stderr_thread, args=(p,))
        
            err_thread.start()
            out_thread.start()
        
            out_thread.join()
            err_thread.join()
        
            return stdout_result + stderr_result
        

        在需要的时候,我认为很容易将输出或错误收集在一个字符串中并返回。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2021-10-28
          • 2013-10-13
          • 2012-06-26
          • 1970-01-01
          • 2010-09-18
          • 2012-08-03
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多