Python子进程完成,但输出文件不可用

1 投票
2 回答
1797 浏览
提问于 2025-04-18 02:43

我的Python代码使用一个子进程通过命令行调用“ifconfig”,并用“>”把输出写入一个文本文件。当这个子进程完成并返回成功时,我会读取这个输出文件。我是定时这样做的,目的是监控网络状态,但有时我无法打开这个输出文件。我刚刚看到Popen有一些可选参数可以用来处理输出和错误,这可能更安全或更好用,但我很好奇为什么我现在的版本会失败。下面是我的代码。里面有一些我库里的对象和宏,没有详细解释,但我觉得代码对于这个问题来说还是比较清晰的。

为什么有时打开输出文件会失败?是不是因为当子进程返回时,文件还没有准备好?有没有什么方法可以确保它准备好可以打开?

       # 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()

2 个回答

0

其实,直接使用 subprocess.Popen() 来处理输出,然后自己把结果写到文件里,可能会更简单一些。如果你想同时获取正常输出和错误输出,那就不能用 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)
3

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

from subprocess import check_output, STDOUT

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

如果你想在 ifconfig 还没完成之前就中断它,并且想读取它的输出,可以查看这个链接:在Python中如何不挂起地停止读取进程输出?

撰写回答