2016-12-20 7 views
1

Я новичок в Python, пытались прибегая к помощи, но не поможет ..
мне нужно вызвать такие команды в трубах (Получить самую старую ожидающую почту от mailq):не Выполнить команду оболочки с трубами в Python

mailq |grep "^[A-F0-9]" |sort -k5n -k6n |head -n 1 

Команда работает в оболочке.

В Python я написал следующее:

p = subprocess.Popen('mailq |grep \"^[A-F0-9]\" |sort -k5n -k6n |head -n 1', shell=True, 
         stdin=subprocess.PIPE, 
         stdout=subprocess.PIPE, 
         stderr=subprocess.STDOUT) 
response = p.communicate()[0] 

Но я получаю такой результат:

сортировки: Ошибка записи: стандартный вывод: Broken трубы \ nsort: Ошибка записи \ п

Хотите знать, что вызывает такую ​​ошибку?

+0

не уверен, но 'STDIN = subprocess.PIPE' кажется излишним и может быть проблемой. Вы также можете рассмотреть возможность отказаться от всего, кроме 'mailq', и обрабатывать вывод в python, а не вызывать все эти дополнительные программы (и я ожидаю, что там где-то есть модуль для замены mailq). Скрывать двойные кавычки также вызывает подозрение, хотя я сомневаюсь, что это вызовет эту проблему. – cdarke

+0

@cdarke попытался удалить набор stdin, но это не помогло. Поэтому вы предлагаете не вызывать команду оболочки, а работать с mailq с помощью какой-либо готовой библиотеки? – 0x49D1

+0

Вы не используете какие-либо команды оболочки, которые я вижу, 'grep',' sort', 'head' - это все независимые программы. Регулярные выражения и сортировка являются встроенными в python. – cdarke

ответ

2

Я думаю, что это должно работать:

p = subprocess.Popen('mailq |grep \"^[A-F0-9]\" |sort -k5n -k6n |head -n 1', shell=True, 
         stdin=subprocess.PIPE, 
         stdout=subprocess.PIPE, 
         stderr=subprocess.PIPE) 
response = p.stdout.readlines(-1)[0] 
print response 

печатает первую строку ответа

+0

ups, исправлено это сейчас – UN4

+0

Не знаю, почему, но на самом деле ваш ответ дает правильный ответ с небольшими изменениями: 'p.stdout.readline (-1)'. Я имею в виду, почему больше нет ошибок с трубами ?! – 0x49D1

+0

Ах, почему-то я думал, что вам нужна только первая линия. Да, удаление '[0]' дает полную выходную информацию. – UN4

1

Вместо того, чтобы сделать оболочку, позаботьтесь о том, чтобы разделить вашу команду на несколько процессов и проложить их, сделайте это сами. См. here, как передать один поток подпроцесса в другой подпроцесс.

Таким образом, вы можете искать выходные данные каждого шага (например, путем маршрутизации stdout на ваш stdout, просто для отладки) и выяснить, работает ли весь ваш рабочий процесс.

Это будет выглядеть немного так:

mail_process = subprocess.Popen('mailq', stdin=PIPE, stdout=PIPE, stderr=STDOUT) 
grep_process = subprocess.Popen(['grep', '\"^[A-F0-9]"'], stdin=mail_process.stdout, stdout=PIPE, stderr=STDOUT] 
... 
head_process = subprocess.Popen(["head", ...], ...) 
head_process.communicate()[0] 
0

Я предлагаю вам использовать подпроцесс, как написано здесь: http://kendriu.com/how-to-use-pipes-in-python-subprocesspopen-objects

ls = subprocess.Popen('ls /etc'.split(), stdout=subprocess.PIPE) 
grep = subprocess.Popen('grep ntp'.split(), stdin=ls.stdout, stdout=subprocess.PIPE) 
output = grep.communicate()[0] 

Это вещий способ использования труб.