2009-09-10 3 views
1

У меня есть команда вроде этого.Как получить выход из внешнего командного комбайна с помощью трубки

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

И я хочу его выход в питон скрипт, я попробовал этот код

>>> 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 вы должны использовать только одну командную строку вместо массива, в противном случае ваши дополнительные аргументы интерпретируются как аргументы оболочки. Из subprocess documentation:

В Unix с оболочкой = True: Если арг является строкой, то он определяет командную строку для выполнения через оболочку. Если args - это последовательность, первый элемент указывает командную строку, и любые дополнительные элементы будут рассматриваться как дополнительные аргументы оболочки.

Таким образом, ваш вызов должен быть:

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 

При необходимости, я думаю, что легко собрать результат или ошибку в строке и вернуться.

Смежные вопросы