使用Python中的信号超时

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了使用Python中的信号超时相关的知识,希望对你有一定的参考价值。

我试图阻止我的UDP客户端程序在服务器丢失数据包的情况下永远等待。我想用信号来实现这个。我的代码是:

def handler(signum):
    raise TimeoutException("Timeout occured!")

signal.signal(signal.SIGALRM, sig_alarm)
sock.sendto(data,serv)
signal.alarm(5)

try:
    received_time, servaddr = sock.recvfrom(size)
except TimeoutException:
    print "timeout"

signal.alarm(0)

在远程服务器关闭的实例中运行此代码时,出现以下错误:

global name 'TimeoutException' is not defined

我假设程序没有“看到”我的处理程序。可能导致什么呢?

答案

TimeoutExceptionPython 2标准库中没有Python 3异常类型。在Python 3.3及更新版本中,有一个TimeoutError类型,当操作系统调用在系统中超时时(相应于errno被设置为ETIMEDOUT值)。但是,我不建议您自己提高此值,因为它的特定意图是响应操作系统返回的超时而引发。

Correct use of signal.signal

在您的comment中,在定义自定义超时异常类型后,您指示出现进一步的错误:handler() takes exactly 1 argument (2 given)

发生这种情况是因为您的信号处理程序不遵循signal package(Python 3的那些文档,但与Python 2相同)所期望的信号处理函数的定义:

signal.signal(signum, handler)

将信号signalnum的处理程序设置为函数处理程序...使用两个参数调用处理程序:信号编号和当前堆栈帧

要解决此问题,请调整自定义信号处理程序的定义,以将堆栈帧作为第二个参数接收。你需要在函数调用中接受这个,正如标准库所期望的那样,但你不需要对传入的值做任何事情。

def handler(signum, frame):
    raise TimeoutException("Timeout occurred!")

Better way? Use socket.settimeout

socket library中有内置的支持,你要完成的是:套接字对象的settimeout method。我建议在你的代码中使用它,而不是试图重新发明轮子;它在抽象实现细节的同时声明了意图,并且有一个内置的异常类型(socket.timeout),您可以捕获它来确定何时发生超时。

使用此方法,您只需在进行阻塞调用之前在套接字上调用socket.settimeout(5),这可能会超时。您还可以在打开应用程序中的第一个套接字之前使用socket.setdefaulttimeout在所有套接字上设置默认超时。


TimeoutException最初来自哪里?

显然,你对它的使用可能源于任何地方。但是,我注意到Selenium中有一个TimeoutException,它是一个广泛使用的Python库,用于自动化浏览器。它被广泛使用,与Selenium相关的示例/ Q&A很常见,所以如果您找到文档或示例使您认为这是标准库中存在的异常类型,我不会感到惊讶,而它实际上是特定于那个图书馆。似乎与Selenium相关的任何内容都不适用于您目前的用例。

另一答案

对于此错误:global name 'TimeoutException' is not defined表示您必须声明自定义异常..这样做的简单方法是将其添加到您的代码中:

class TimeoutException(Exception): pass

有一点需要注意的是,selenium有一个名为TimeoutException的异常,它不是标准库中存在的异常类型,但特定于selenium库:

from selenium.common.exceptions import TimeoutException

最后你会遇到另一个错误,因为你的信号处理程序必须接收堆栈帧作为第二个参数(使用两个参数调用处理程序:信号编号和当前堆栈帧):

def handler(signum, frame): raise TimeoutException("Timeout occurred!")

请阅读文档minimal example program中的以下示例

以上是关于使用Python中的信号超时的主要内容,如果未能解决你的问题,请参考以下文章

QTimer 超时信号不发出

如何在现代 Linux 上的 Perl 中运行程序(超时)并知道它是如何结束的(信号、退出代码等)?

谷歌地图片段显示,但没有地图

测试片段不执行定时器或示例超时

Python 开发个人微信号在运维开发中的使用

com.android.inputmethod.latin 中的 ANR 原因:输入调度超时