Python子进程 - stderr在读取后擦除

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Python子进程 - stderr在读取后擦除相关的知识,希望对你有一定的参考价值。

我正在使用python 2.7并尝试检查执行的前10秒内的stderr是否返回任何错误,如果没有,继续该过程,我不是在等待该过程结束,因为它是一个循环。

我得到了这段代码:

p = subprocess.Popen(
            ["python", os.getcwd() + "/start.py", 1hr, 30min, 0, 0],
            stdout=subprocess.PIPE, stderr=subprocess.PIPE)
        if len(p.stderr.readlines()) is not None:
            print p.stderr.readlines()
            return jsonify(status="failed",
                           error_details=p.stderr.readlines()
                           )

问题是,在读完stderr的长度后,stderr会自行清除,因此我无法检查值并发布消息,因此print p.stderr.readlines()变为空列表。

{
  "error_details": [], 
  "status": "failed"
}

我不想显示输出,我只想运行start.py并检查错误,如果没有错误在10秒左右出现,这意味着一切顺利,并且可以继续并运行在后台子进程启动的循环没有检查它。我可以以某种方式继续,如果p进程即使在1小时左右后仍然无法返回错误,执行回调?我可以以某种方式存储stderr来回复消息吗?另外,你如何建议我在10秒内制作一个计数器来检查是否弹出错误?即使文件不存在,使用p.pool()也不会返回任何错误代码。

答案

当然你可以存储readlines的结果,所以你不消耗缓冲区,但你的代码有一个更严重的问题。

使用subprocess.PIPE用于stdoutstderr并尝试读取stderr之后可能导致死锁。

此外,在某些情况下,该过程可以无声地失败,并且没有任何内容写入stderr。这不是获取返回代码的正确方法。

唯一(更简单的方法)是使用communicate

p = subprocess.Popen(
            ["python", os.getcwd() + "/start.py", "1hr", "30min", "0", "0"],
            stdout=subprocess.PIPE, stderr=subprocess.PIPE)
out,err = p.communicate()
rc = p.wait()
if rc: # non-zero return code
        return jsonify(status="failed",
                       error_details=err.decode().splitlines())

您可以透明地在2个单独的线程中读取输出和错误(不会出现死锁),并测试返回码。如果不为零,则发生错误。拆分解码器错误输出(python 3)的行并返回错误。

请注意,splitlines()删除了行终止(而不是流上的readlines())。

上述方法无法处理“等待10秒然后测试错误输出”的方法。这个可以:

p = subprocess.Popen(
            ["python", os.getcwd() + "/start.py", "1hr", "30min", "0", "0"],
            stdout=subprocess.DEVNULL, # don't read stdout, avoids deadlock
            # stdout=devnull, # python 2, where devnull = open(os.devnull, 'w')
            stderr=subprocess.PIPE)
# now wait 10 seconds
time.sleep(10)
if p.poll() is not None and p.poll() != 0:    
    return jsonify(status="failed",
                   error_details=p.stderr.readlines() # add .decode() for python 3
                   )

上述方法等待10秒,然后测试进程是否以错误结束,返回错误/读取错误输出。

以上是关于Python子进程 - stderr在读取后擦除的主要内容,如果未能解决你的问题,请参考以下文章

在 Docker 上运行的 Mongodb 正在重新启动后擦除集合

Python分别从子进程stdout和stderr读取,同时保留顺序

使用 CGContext 绘制后擦除

wxpython 使用 DC 后擦除背景

如何在python中杀死一个分叉的孩子及其jackd子进程

Python监控子进程的stderr和stdout