Python:使用Signal.Alarm进行超时异常处理 [英] Python: Timeout Exception Handling with Signal.Alarm

查看:1050
本文介绍了Python:使用Signal.Alarm进行超时异常处理的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如果函数调用花费的时间太长,我正在尝试实现超时异常处理程序。

I am trying to implement a timeout exception handler if a function call is taking too long.

EDIT :实际上,我在使用子过程编写Python脚本,该子过程调用带有参数的旧C ++程序。我知道该程序会不时挂起,不会返回任何内容。这就是为什么我试图设置一个时限,并转到带有不同参数等的下一个呼叫。

EDIT: In fact, I am writing a Python script using subprocess, which calls an old C++ program with arguments. I know that the program hangs from time to time, not returning anything. That's why I am trying to put a time limit and to move on to next call with different argument and etc.

我一直在搜索并尝试实现它,但是它不是很有效,所以我希望得到一些帮助。到目前为止,我所拥有的是:

I've been searching and trying to implement it, but it doesn't quite work, so I wish to get some help. What I have so far is:

#! /usr/bin/env python

import signal

class TimeOutException(Exception):
    def __init__(self, message, errors):
        super(TimeOutException, self).__init__(message)
        self.errors = errors

def signal_handler(signum, frame):
    raise TimeOutException("Timeout!")

signal.signal(signal.SIGALRM, signal_handler)
signal.alarm(3)

try:
    while True:
        pass

except TimeOutException:
    print "Timed out!"

signal.alarm(0)

编辑:我目前收到的错误消息是 TypeError: init ()恰好接受3个参数(给定2个)

EDIT: The Error message I receive currently is "TypeError: init() takes exactly 3 arguments (2 given)

另外,我想问一个有关except块的基本问题, TimeOutException除外的代码与异常处理程序中的代码之间的角色区别是什么?看来两者都可以做相同的事情?

Also, I would like ask a basic question regarding the except block. what's the role difference between the code right below "except TimeOutException" and the code in the "Exception handler"? It seems both can do the same thing?

任何帮助将不胜感激。

推荐答案


太长了

if a function call is taking too long

我意识到这对于没有经验的开发人员可能并不明显,但是解决此问题的方法完全取决于您

I realize that this might not be obvious for inexperienced developers, but the methods applicable for approaching this problem entirely depend on what you are doing in this "busy function", such as:


  • 这是繁重的计算吗?如果是的话,哪个Python解释器是您使用的是CPython还是PyPy?如果是CPython:此计算仅使用P ython字节码还是它涉及外包给编译后的机器代码的函数调用(可能会占用Python的Global Interpreter Lock相当长的不可控制的时间)?

  • Is this a heavy computation? If yes, which Python interpreter are you using? CPython or PyPy? If CPython: does this computation only use Python bytecode or does it involve function calls outsourced to compiled machine code (which may hold Python's Global Interpreter Lock for quite an uncontrollable amount of time)?

这是吗?大量的I / O工作?如果是,您可以在任意状态下中止此I / O工作吗?还是需要适当清理?您使用的是gevent还是Twisted等框架?

Is this a lot of I/O work? If yes, can you abort this I/O work in an arbitrary state? Or do you need to properly clean up? Are you using a certain framework such as gevent or Twisted?

编辑:
因此,看起来您只是在生成一个子进程并等待其终止。太好了,实际上这是实现超时控制的最简单问题之一。 Python(3)附带了相应的功能! :-)

So, it looks you are just spawning a subprocess and wait for it to terminate. Great, that is actually one of the most simple problems to implement a timeout control for. Python (3) ships a corresponding feature! :-) Have a look at

https://docs.python.org/3/library/subprocess.html#subprocess.call


timeout参数传递给Popen.wait()。如果超时
到期,子进程将被终止,然后再次等待。
子进程
终止后,将重新引发TimeoutExpired异常。

The timeout argument is passed to Popen.wait(). If the timeout expires, the child process will be killed and then waited for again. The TimeoutExpired exception will be re-raised after the child process has terminated.

Edit2:

适合您的示例代码,将其保存到文件中并至少使用Python 3.3执行:

Example code for you, save this to a file and execute it with Python 3.3, at least:

import subprocess


try:
    subprocess.call(['python', '-c', 'print("hello")'], timeout=2)
except subprocess.TimeoutExpired as e:
    print("%s was terminated as of timeout. Its output was:\n%s" % (e.cmd, e.output))


try:
    subprocess.call(['python'], timeout=2)
except subprocess.TimeoutExpired as e:
    print("%s was terminated as of timeout. Its output was:\n%s" % (e.cmd, e.output))

在第一种情况下,子进程立即返回。不会引发超时异常。在第二种情况下,超时到期,并且您的控制进程(在脚本上方运行的进程)将尝试终止子进程。这样成功了。之后,引发 subprocess.TimeoutExpired ,异常处理程序对其进行处理。对我来说,上面的脚本的输出是 ['python'],由于超时而终止。其输出为:

In the first case, the subprocess immediately returns. No timeout exception will be raised. In the second case, the timeout expires, and your controlling process (the process running above's script) will attempt to terminate the subprocess. This succeeds. After that, the subprocess.TimeoutExpired is raised and the exception handler deals with it. For me the output of the script above is ['python'] was terminated as of timeout. Its output was: None:

这篇关于Python:使用Signal.Alarm进行超时异常处理的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆