Python - 使用Popen.communicate()不会按预期捕获系统调用的stdout和stderr

时间:2014-03-18 15:01:02

标签: python subprocess

我有一个执行系统调用的Python脚本(该调用实际上是一个java程序)。 我正在使用Popen.communicate() 尝试来捕获stdoutstderr。但是,它仅适用于某些Java应用程序(其中,我调用的所有java应用程序在直接在shell中执行时会向屏幕显示内容。)

我使用的代码如下:

    # Perform the java call
    try:

        p = subprocess.Popen(args,
                             stdout=subprocess.PIPE,
                             stderr=subprocess.PIPE)

    except OSError as e:
        error_msg = '  Error reading file while executing system command: {0}'.format(e.message)

    except ValueError as e:
        error_msg = '  Error in arugments while executing system command: {0}'.format(e.message)

    else:
        # Display the results in real time
        for line in iter(p.stdout.readline, ''):
            sys.stdout.write(line)

        # Grab the stdout and stderr from the process.
        output, err = p.communicate()

    finally:
        # Check to see if an internal error occurred. If not, flip the flag
        if not err and not error_msg:
            java_completed = True
        else:
            java_completed = False

在某些情况下,行sys.stdout.write(line)永远不会被调用,而在其他情况下则是。

有没有人有这方面的经验?

1 个答案:

答案 0 :(得分:1)

我注意到的第一件事是你从进程标准输出中读取所有内容,然后尝试communicate之后:你已经读过管道中的所有内容,所以{{{ 1}}来自output的结果将始终为空。

但这并不能解释为什么有时p.communicate()没有被调用。

要记住的一件事是,有多种方法可以在控制台中显示内容(即在命令窗口中)。打印到流程标准输出流只是一种方式,这是您使用上述代码捕获的方式。如果我从Java时代开始回忆,有些类型的sys.stdout.write类有时用于向控制台显示,这可能不会使用stdout。此外,高级控制台显示库(例如Console)通常不会写入stdout,它们会直接与控制台对象进行交互。我不知道如何或者是否可以从这些类型的流程中捕获输出,但如果可能的话,它可能是非常特定于系统的。