如何检测Python子进程中的超时是否已经达到?

如何检测Python子进程中的超时是否已经达到?

问题描述:

我想区分失败的进程和超时进程。 Python 确实捕获错误并清楚地标识它。这很好,但没有雪茄,因为我想写我自己的日志消息,对应于超时错误。请参阅下面的我目前的实施和我想要的解释。如何检测Python子进程中的超时是否已经达到?

如果程序是这样的:

#!/usr/bin/env python3 

""" 
My job is to demonstrate a problem detecting timeout failures. 
""" 

import os 
import sys 
import logging 
import subprocess 
import time 

# Create main (root) logging object 
logger = logging.getLogger('{}'.format(__file__)) 
logger.setLevel(logging.DEBUG) 

# Formatter 
consoleh = logging.StreamHandler(sys.stdout) 
consoleh.setLevel(logging.INFO) 
console_formatter = logging.Formatter('%(asctime)s %(name)s PID: %(process)d TID: %(thread)d %(levelname)s \n ==> %(message)s',datefmt='%Y-%m-%d at %H:%M:%S.%s') 
consoleh.setFormatter(console_formatter) 
logger.addHandler(consoleh) 

def preHook(script): 
    logger.debug('preHook called.') 
    command = "{}".format(script) 
    logger.info('preHook Executing with 15 second timeout: \n  /bin/sh -c {}'.format(command)) 
    process = subprocess.Popen(command,stdout=subprocess.PIPE,stderr=subprocess.PIPE,shell=True)# timeout in seconds 
    process.wait(timeout=15) 
    proc_stdout, proc_stderr = process.communicate() 
    if process.returncode == 0: 
    logger.info('preHook: Process complete: \n  Command: /bin/sh -c {}\n  STDOUT: "{}"\n  STDERR: "{}"\n  Exit Code: {}\n  at: {}'.format(command,proc_stdout.decode('utf8').strip(),proc_stderr.decode('utf8').strip(),process.returncode,time.time())) 
    else: 
    exitcode = 1 
    logger.error('preHook: Process failed: \n  Command: /bin/sh -c {}\n  STDOUT: "{}"\n  STDERR: "{}"\n  Exit Code: {}\n  at: {}'.format(command,proc_stdout.decode('utf8').strip(), proc_stderr.decode('utf8').strip(),process.returncode,time.time())) 

def main(): 
    preHook('find -type f') 

if __name__ == "__main__": 
    main() 

我如何能赶上超时错误,并在标准错误输出写入相关的消息?

控制台输出

Python的子进程包明显捕获超时错误。

2017-08-28 at 09:44:57.1503906297 detecttimeout.py PID: 16915 TID: 140534594959104 INFO 
==> preHook Executing with 15 second timeout: 
    /bin/sh -c find -type f 
Traceback (most recent call last): 
    File "detecttimeout.py", line 40, in <module> 
    main() 
    File "detecttimeout.py", line 37, in main 
    preHook('find -type f') 
    File "detecttimeout.py", line 28, in preHook 
    process.wait(timeout=15) 
    File "/home/USER/devel/python/Python-3.4.5/Lib/subprocess.py", line 1561, in wait 
    raise TimeoutExpired(self.args, timeout) 
subprocess.TimeoutExpired: Command 'find -type f' timed out after 15 seconds 

我想赶上超时,就像我做失败的过程。为了实现捕获失败的进程,我使用逻辑中显示的返回代码。消息preHook: Process failed...发生。我想再发一条消息:preHook: Process timed out...

+0

为什么不更换

process.wait(timeout=15) 

只需捕获TimeoutExpired异常即可并在except子句中写出你想要的消息? – Anis

+0

@Anis当然,你可以通过提供一个描述如何实现这一点的答案来帮助我吗? –

您可以通过

try: 
    process.wait(timeout=15) 
except subprocess.TimeoutExpired: 
    logger.error(<your error message>) 
    return 

刚捕获的错误

try: 
    process.wait(timeout=15) 
except subprocess.TimeoutExpired as e: 
    logger.error(e) #logs the default error from subprocess.TimeoutExpired 
    logger.error("Boom") 
    return 

编辑:更加准确,记录错误消息以及

+0

感谢您的帮助。只是因为Anis速度更快,我会把它交给Anis。千钧一发。 –

+0

@JonathanKomar当然,他可能会更准确(subprocess.TimeoutExpired),相应地编辑我的答案,并显示如何打印默认错误,如果你确实需要它。 –