当前位置: 首页 > 面试题库 >

包装子进程的stdout / stderr

李和昶
2023-03-14
问题内容

我想捕获并显示通过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

对我而言,重要的是要立即显示子html" target="_blank">流程的输出。我尝试使用subprocess.PIPE捕获输出并手动显示,但是一旦处理完成,我只能使它显示输出。但是,我想实时查看输出。


问题答案:

进程的Stdin,stdout和stderr必须是真实的文件描述符。(这实际上不是Python施加的限制,而是管道在OS级别上的工作方式。)因此,您将需要一个不同的解决方案。

如果你想同时跟踪stdoutstderr实时,你需要异步I / O或线程。

  • 异步I / O: 使用标准的同步(=阻塞)I / O,可能会阻塞对其中一个流的读取,从而不允许实时访问另一个流。如果你是在Unix上,你可以使用非阻塞I / O中的说明这个答案。但是,在Windows上,您将无法使用这种方法。该视频介绍了更多有关Python中异步I / O的信息,以及一些替代方法。

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



 类似资料:
  • 我试图与一个进程通信(该进程本身会写入stdin和stdout,以便在终端中与用户交互),并在C中读取它的stdin和写入它的stdout。 因此,我尝试以编程方式替换shell用户。一个methapohrical示例:假设出于某种原因我想在C中使用VIM。然后我还需要编写命令(stdout)并从编辑器(stdin)中读取内容。 起初我认为这可能是一项微不足道的任务,但似乎没有标准的方法<代码>i

  • 我正在学习,但我对这段代码有点困惑: 输出: 如您所见,输出是格式化的。但是我不知道为什么结尾有字符和。 如果我在终端中运行此命令,则没有这些字符。 正常输出: 我怎样才能移除它们?

  • 问题内容: 我正在用Go编写程序,该程序执行类似程序的服务器(也就是Go)。现在,我想在启动父程序的终端窗口中获​​得子程序的标准输出。一种方法是使用函数,但这仅在进程退出后才输出标准输出。(这是一个问题,因为这个类似于服务器的程序运行了很长时间,并且我想读取日志输出) 变量是,我不知道该如何使用它来完成任务,因此我在网络上找不到有关此主题的任何有用信息。 对代码的解释:取消注释该函数以获取要编译

  • 问题内容: 这是此问题的后续措施,但是如果我想将参数传递给,如何实时获取输出?这就是我目前拥有的;我也尝试从模块中替换为,这只会导致脚本挂起。 在我不必通过的前一个问题中,建议我使用,没有空间输送任何东西到。 附录:这适用于传输,但是我只能在最后看到输出,并且我想查看传输发生时的详细信息。 问题答案: 为了实时从子流程中获取标准输出,您需要准确确定所需的行为;具体来说,您需要确定是要逐行处理还是逐

  • 问题内容: 我试图从通话中抢夺,尽管我可以通过以下方式轻松实现此目标: 我想“实时”抓取。使用上述方法,PIPE等待获取所有内容,然后返回。 因此,出于日志记录目的,这不符合我的要求(例如,“查看”发生的情况)。 在运行时,有没有办法逐行获取?或者这是(必须等到关闭)的限制。 编辑 如果我切换为我只得到(不理想)的最后一行: 问题答案: 您的解释器正在缓冲。在打印语句后,添加对sys.stdout

  • 问题内容: 我需要运行一个程序并将其输出收集到stdout。这个程序(socat)需要在python脚本期间在后台运行。Socat一旦运行,便处于dameon模式,但首先,它将向我的其余脚本输出一些行到stdout。 命令: 输出: … 我基本上想在程序开始时运行它,并保持运行直到脚本终止,但是我需要将两个/ dev / pts / X名称读入python。 谁能告诉我该怎么做? 我想出了这个挂起