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

使用subprocess.Popen处理大型输出

谢鸿飞
2023-03-14
问题内容

我有一些Python代码可以执行一个外部应用程序,当该应用程序的输出量很少时,它可以很好地运行,但是在有大量输出时,它会挂起。我的代码如下:

p = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
errcode = p.wait()
retval = p.stdout.read()
errmess = p.stderr.read()
if errcode:
    log.error('cmd failed <%s>: %s' % (errcode,errmess))

文档中有一些注释似乎表明了潜在的问题。等待中,有:

警告:如果子进程向stdoutstderr管道生成足够的输出,从而阻塞等待OS管道缓冲区接受更多数据的输出,则将死锁。使用communicate()避免这种情况。

尽管进行了交流,但我发现:

注意读取的数据缓存在内存中,因此,如果数据大小很大或没有限制,则不要使用此方法。

因此,对我来说不清楚的是,如果我有大量数据,则应使用这两种方法之一。他们没有指出在那种情况下我应该使用哪种方法。

我确实需要exec的返回值,并且要解析并使用stdoutstderr

那么在Python中执行外部应用程序的等效方法是什么?


问题答案:

您正在阻止对两个文件的读取。第一个需要在第二个开始之前完成。如果应用程序向写入了很多内容stderr,而对却没有写入任何内容stdout,那么您的进程将坐在那里等待stdout不来的数据,而您正在运行的程序坐在那里等待被写入的内容stderr被读取(从不因为-
您正在等待stdout)。

有几种方法可以解决此问题。

最简单的是不拦截stderr;
离开stderr=None。错误将直接输出到stderr。您无法拦截它们并将其显示为您自己的消息的一部分。对于命令行工具,这通常是可以的。对于其他应用程序,这可能是个问题。

另一种简单的方法是重定向stderrstdout,因此您只有一个传入文件:set
stderr=STDOUT。这意味着您无法将常规输出与错误输出区分开。根据应用程序如何写入输出,这可能会接受也可能无法接受。

处理此问题的完整且复杂的方法是select(http://docs.python.org/library/select.html)。这使您能够以非阻塞方式进行读取:只要数据出现在stdout或上,就可以获取数据stderr。如果确实需要,我只会建议这样做。这可能在Windows中不起作用。



 类似资料:
  • 问题内容: 我已经通过以下网址访问了StreamGobbler JavaWorld:Stream Gobbler 我了解用法及其实施原因。但是,所涵盖的方案仅是那些可能存在命令/处理错误的输出的方案。 我找不到任何使用StreamGobbler来处理输入的情况。例如,在中,我必须指定电子邮件的正文,并按照以下格式进行操作 如何通过StreamGobbler处理此问题,或者不需要通过它进行处理。 问

  • 问题内容: 我正在尝试处理较大的(可能多达200M)JSON文件。文件的结构基本上是对象数组。 因此,遵循以下原则: 每个对象都具有任意属性,不必与数组中的其他对象共享它们(例如,具有相同的属性)。 我想对数组中的每个对象进行处理,并且由于文件可能很大,因此无法将整个文件内容都包含在内存中,无法解码JSON并遍历PHP数组。 因此,理想情况下,我想读取文件,为每个对象获取足够的信息并进行处理。如果

  • 我正在编写一个程序,使用Spring Batch处理MySQL数据库表中的7637064行。我成功地处理了较小的表,但当JdbcCursorItemReader尝试打开光标时,该表中的大量行导致了OutOfMemoryError异常。 我可能可以通过向它扔一个更大的Xmx来解决这个问题,但在我看来,Spring Batch应该有办法处理这个问题,我可能只是缺少一个关键的配置部分。 Spring批配

  • 问题内容: 我有一个很大的xml文件,其中包含许多子元素。我希望能够运行一些xpath查询。我尝试在Java中使用vtd- xml,但有时会出现内存不足错误,因为xml太大,无法容纳到内存中。是否有替代方法来处理如此大的xml。 问题答案: 尝试http://code.google.com/p/jlibs/wiki/XMLDog 它使用sax执行xpaths,而无需创建xml文档的内存表示形式。

  • 问题内容: 我有点想了解解决这个简单问题的python方法是什么。 我的问题很简单。如果使用以下代码,它将挂起。子流程模块doc中对此进行了详细记录。 搜索一个解决方案(有一个非常有见地的线程,但是我现在已经迷失了),我发现这个解决方案(以及其他)使用了一个显式的fork: 尽管此解决方案在概念上非常容易理解,但它使用了一个以上的进程,并且与子进程模块相比,其停留在太低的级别(那只是为了隐藏此类事

  • 我正在处理非常大的文件,并使用Spring集成来处理它们。我想知道使用Spring集成和提供的DSL处理这些问题的最佳和最有效的方法是什么。我有一个测试CSV文件,它有大约30K条记录,我正在使用filespliter组件将每一行读入内存,然后根据分隔符再次拆分,以获得我需要的列。 下面的代码段。