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

时间:2018-03-02 11:29:35

标签: python python-2.7 subprocess popen

我正在使用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()也不会返回任何错误代码。

1 个答案:

答案 0 :(得分:2)

当然,您可以存储readlines的结果,这样您就不会使用缓冲区,但您的代码存在更严重的问题。

subprocess.PIPEstdout使用stderr并在此之后尝试阅读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秒,然后测试进程是否以错误结束,返回错误/读取错误输出。