2010-08-11 6 views
1

Я хочу, чтобы иметь возможность использовать Popen.communicate и имеют стандартный вывод записывается в файл (в дополнение к тому, что вернулся из communicate()Python subprocess.Popen общаться через трубопровод

Это делает то, что я хочу. - но это на самом деле хорошая идея?

cat_task = subprocess.Popen(["cat"], stdout=subprocess.PIPE, stdin=subprocess.PIPE) 
tee_task = subprocess.Popen(["tee", "-a", "/tmp/logcmd"], stdin=cat_task.stdout, 
    stdout = subprocess.PIPE, close_fds=True) 
cat_task.stdout = tee_task.stdout #since cat's stdout is consumed by tee, read from tee. 
cat_task.communicate("hello there") 
('hello there', None) 

Любые проблемы, связанные с этим, глядя на сообщаться-х осущ выглядит хорошо. Но есть более хороший способ?

ответ

1

в зависимости от вашего определения «лучше», я бы сказал, что следующее возможно лучше в том смысле, что избавляет от необходимости дополнительного процесс тройника:

import subprocess 

def logcommunicate(self, s): 
    std = self.oldcommunicate(s) 
    self.logfilehandle.write(std[0]) 
    return std 

subprocess.Popen.oldcommunicate = subprocess.Popen.communicate 
subprocess.Popen.communicate = logcommunicate 
logfh = open("/tmp/communicate.log", "a") 

proc = subprocess.Popen(['cat'], stdin=subprocess.PIPE, stdout=subprocess.PIPE) 
proc.logfilehandle = logfh 

result = proc.communicate("hello there\n") 
print result 

В двух словах, он обеспечивает оболочку для communicate(), который записывает стандартный вывод в файл ручку по вашему выбору, а затем возвращает исходный кортеж для вас использовать. Я исключил обработку исключений; вы должны, вероятно, добавить, что если программа более критична. Кроме того, если вы планируете создать несколько объектов Popen и хотите, чтобы все они регистрировались в одном файле, вам, вероятно, следует упорядочить для logcommunicate() потокобезопасность (синхронизированная на дескриптор файла). Вы можете легко расширить это решение для записи в отдельные файлы для stdout и stderr.

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

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