包装子进程的stdout/stderr
我想通过Python的subprocess模块来捕获并显示一个进程的输出。
我以为可以直接把我的文件对象作为参数传给stdout和stderr。
我看到它访问了fileno
属性,所以它确实在对这个对象做一些操作。不过,write()
方法从来没有被调用。我的方法完全错了吗,还是我只是漏掉了什么?
class Process(object):
class StreamWrapper(object):
def __init__(self, stream):
self._stream = stream
self._buffer = []
def _print(self, msg):
print repr(self), msg
def __getattr__(self, name):
if not name in ['fileno']:
self._print("# Redirecting: %s" % name)
return getattr(self._stream, name)
def write(self, data):
print "###########"
self._buffer.append(data)
self._stream.write(data)
self._stream.flush()
def getBuffer(self):
return self._buffer[:]
def __init__(self, *args, **kwargs):
print ">> Running `%s`" % " ".join(args[0])
self._stdout = self.StreamWrapper(sys.stdout)
self._stderr = self.StreamWrapper(sys.stderr)
kwargs.setdefault('stdout', self._stdout)
kwargs.setdefault('stderr', self._stderr)
self._process = subprocess.Popen(*args, **kwargs)
self._process.communicate()
更新:
我还希望能够使用ANSI控制字符来移动光标和覆盖之前输出的内容。我不知道这是不是正确的说法,但我举个例子:我想自动化一些GIT的操作,在那里进度会自我更新,而不是每次都换新的一行。
更新 2
对我来说,子进程的输出能够立即显示是很重要的。我尝试使用subprocess.PIPE来捕获输出并手动显示,但我只能在进程完成后才看到输出。然而,我希望能实时看到输出。
5 个回答
0
可以看看这里。
p = subprocess.Popen(cmd,
shell=True,
bufsize=64,
stdin=subprocess.PIPE,
stderr=subprocess.PIPE,
stdout=subprocess.PIPE)
0
文件类型不够准确。它必须是真正的文件,并且要有一个真实的文件描述符。可以使用subprocess
来处理管道,并根据需要从中读取数据。
12
一个程序的标准输入(stdin)、标准输出(stdout)和标准错误(stderr)需要是真正的文件描述符。(这其实不是Python的限制,而是操作系统层面上管道的工作方式。)所以你需要找其他的解决办法。
如果你想实时跟踪stdout
和stderr
,你就需要使用异步输入输出或者线程。