首页 文章

换行子进程'stdout / stderr

提问于
浏览
7

我想捕获并显示我通过Python的子进程调用的进程的输出 .

我以为我可以将我的文件类对象作为命名参数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来捕获输出,并手动显示它,但是我只能在进程完成后才能显示输出 . 但是,我想实时看到输出 .

4 回答

  • 12

    进程的Stdin,stdout和stderr需要是真正的文件描述符 . (这实际上不是Python强加的限制,而是管道在操作系统级别上的工作方式 . )因此,您需要一个不同的解决方案 .

    如果要实时跟踪 stdoutstderr ,则需要异步I / O或线程 .

    • Asynchronous I/O: 使用标准同步(=阻塞)I / O,对其中一个流的读取可能会阻塞,从而不允许实时访问另一个流 . 如果您使用的是Unix,则可以使用this answer中所述的非阻塞I / O.但是,在Windows上,你会对这种方法感到不快 . 有关Python中的异步I / O的更多信息以及this video中显示的一些替代方法 .

    • Threads: 解决此问题的另一种常用方法是为要实时读取的每个文件描述符创建一个线程 . 线程只处理它们所指向的文件描述符,因此阻塞I / O不会造成损害 .

  • 0

    看看here .

    p = subprocess.Popen(cmd,
                     shell=True,
                     bufsize=64,
                     stdin=subprocess.PIPE,
                     stderr=subprocess.PIPE,
                     stdout=subprocess.PIPE)
    
  • 0

    文件不够接近 . 它必须是具有实际文件描述符的实际文件 . 使用 subprocess 对管道的支持并根据需要从中读取 .

  • -1

    有没有理由在课堂上上课?并且stdout和stderr可以采用任何类似文件的文件,例如try . 所以简单地传递一个打开的文件类型或stringIO应该足以修改流

    import sys
    sys.stdout = open('test.txt','w')
    print "Testing!"
    sys.stdout.write('\nhehehe')
    sys.stdout = sys.__stdout__
    sys.exit(0)
    

相关问题