Python subprocess.Popen 通过管道通信
我想使用 Popen.communicate
,并且希望把标准输出(stdout)记录到一个文件里(除了从 communicate()
返回的内容)。
这样做可以达到我的目的,但这样真的好吗?
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)
这样做有没有什么问题?看了 communicate
的实现,感觉还不错。但是有没有更好的方法呢?
1 个回答
1
根据你对“更好”的定义,我觉得下面这个方法可能更好,因为它避免了额外的tee进程:
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()
提供了一个包装,这个包装会把标准输出(stdout)写入你选择的文件中,然后返回原来的结果给你使用。我省略了异常处理;如果这个程序比较重要,你可能需要加上这部分。另外,如果你打算创建多个Popen
对象,并希望它们都记录到同一个文件中,你可能需要确保logcommunicate()
是线程安全的(也就是说,针对每个文件句柄进行同步)。你也可以很容易地扩展这个方法,让标准输出和标准错误(stderr)写入不同的文件。
需要注意的是,如果你预计会频繁传输大量数据,那么communicate()
可能不是最佳选择,因为它会把所有数据都保存在内存中。