2009-09-10 77 views
1

我有這樣的命令。如何從外部命令結合管道輸出

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 

請幫忙。

回答

7

使用shell=True,您應該使用單個命令行而不是數組,否則您的附加參數將被解釋爲shell參數。從subprocess documentation

在Unix上,shell = True:如果args是一個字符串,它指定要通過shell執行的命令字符串。如果args是一個序列,則第一個項目指定命令字符串,並且任何其他項目將被視爲附加的shell參數。

所以,你的電話應該是:

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

我想你也可能有不平衡的單引號在那裏。

0

因爲你是在傳遞一個序列的程序,它認爲該管道是參數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() 
'' 
0

經過一番研究,我有以下的代碼工作對我非常好。它基本上實時打印stdout和stderr。希望它可以幫助需要它的其他人。

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 

當需要時,我認爲很容易收集字符串中的輸出或錯誤並返回。