【问题标题】:Python Subprocess Finishes, but Output File Not AvailablePython 子进程完成,但输出文件不可用
【发布时间】:2014-04-14 18:56:57
【问题描述】:

我的 python 代码使用子进程通过 shell 调用“ifconfig”并使用“>”将输出写入文本文件。当子进程完成并返回成功时,我读取了输出文件。我定期执行此操作以监视网络状态,但有时我无法打开输出文件。我刚刚读到 Popen 有 stdout 和 stderr 的可选参数,这可能更安全/更好地支持,但我很好奇为什么我当前的版本失败。我的代码如下。我的库中有一些对象和宏没有解释,但我认为代码对于这个问题仍然足够清晰。

为什么打开输出文件偶尔会失败?子进程返回时文件是否可能尚未准备好?有什么方法可以保证它可以打开?

       # Build command line expression.
        expr = 'ifconfig' + ' >' + outputFile + ' 2>&1'

        try:
            # Execute command line expression.
            p = subprocess.Popen(expr, shell=True)
        except:
            Error("Unable to open subprocess.")

        if(p is None):
            Error("Unable to create subprocess.")

        # Wait until command line expression has been executed.
        wait = Wait.Wait(Constants.MIN_TIME_TO_QUERY_NETWORK_INFO, Constants.MAX_TIME_TO_QUERY_NETWORK_INFO)

        #Execute command then wait for timeout.    
        if (wait.StopUntilCondition(operator.ne, (p.poll,), None, True)):
            p.kill()
            Error("Get subnet mask subprocess timed out.")

        if(not p.poll() == 0):
            Error("Failed to get network information from operating system.")

        Warning("About to read output file from get subnet mask...")

        # Read temporary output file.
        f = open(outputFile, "r")
        networkInfo = f.read()
        f.close()

【问题讨论】:

  • 我想知道:对Popen 的调用是等待ifconfig 退出,还是等待重定向完成?
  • 不相关:不要:if(not p.poll() == 0):,不要使用if p.poll() != 0:,尽管您应该在这里使用p.wait()
  • @J.F.Sebastian 感谢关于“not ==" vs "!=" 的注释。我从来没有考虑过,现在知道有区别。关于“if(p.poll() != 0)”,文档说“p.poll()”检查进程是否已终止(在完成之前返回 None,我的 wait.StopUntilCondition 正在等待)和“p.poll()”。 wait()" 等待直到进程终止。看起来一样,但无论如何我可能会选择你的“check_output”答案。谢谢!
  • 请不要使用不必要的括号(Python 不是 C)。 p.wait()(与 p.poll() 不同)断言该过程已完成。
  • @J.F.Sebastian 会在括号里做...很难改掉这个习惯。至于 p.poll() 与 p.wait(),文档似乎没有具体说明,但我相信你的话,某处埋藏着一个断言。 p.wait 的文档说“等待子进程终止。”和 p.poll “检查子进程是否已终止。”。

标签: python subprocess


【解决方案1】:

为了避免损坏/丢失的输出,您应该在尝试读取文件之前调用p.wait()。在这种情况下,您不需要使用文件:

from subprocess import check_output, STDOUT

network_info = check_output('ifconfig', stderr=STDOUT)

如果你想在ifconfig完成之前中断它读取它的输出;见Stop reading process output in Python without hang?

【讨论】:

    【解决方案2】:

    使用subprocess.Popen() 并自己将输出写入文件可能更容易。请注意,如果您想同时捕获 stdout 和 stderr,则不能使用 subprocess.check_output

    try:
        p = subprocess.Popen(['ifconfig'], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
        outdata, errdata = p.communicate()
    except Exception as e:
        print "An error occurred:", e
    with open(outputFile, 'w') as outf:
        outf.write(outdata)
    

    有了这个,您不必等待; communicate 在进程完成之前不会返回。

    如果您只想捕获标准输出,请改用subprocess.check_output

    try:
        outdata = subprocess.check_output(['ifconfig'])
    except Exception as e:
        print "An error occurred:", e
    with open(outputFile, 'w') as outf:
        outf.write(outdata)
    

    【讨论】:

    • -1: check_output 可以用于捕获stdout和stderr(在my answer中显示)。
    猜你喜欢
    • 2013-08-18
    • 1970-01-01
    • 2011-03-08
    • 1970-01-01
    • 2012-02-11
    • 1970-01-01
    • 2016-03-05
    • 2021-09-20
    • 1970-01-01
    相关资源
    最近更新 更多