在Python中使用信号超时

2021-05-13 14:18:16 发布

您现在位置: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)

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

^{pr2}$

我假设程序没有“看到”我的处理程序。是什么原因造成的?在

2条回答
网友
1楼 ·

对于此错误:global name 'TimeoutException' is not defined这意味着u必须声明自定义异常。。简单的方法是在代码中添加以下内容:

class TimeoutException(Exception): pass

值得一提的是,selenium有一个名为TimeoutException的异常,它不是标准库中的异常类型,而是特定于selenium库的异常类型:

from selenium.common.exceptions import TimeoutException

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

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

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

网友
2楼 ·

Python 2或{a2}标准库中没有TimeoutException异常类型。在Python3.3及更高版本中,有一个TimeoutError类型,当系统中的操作系统调用超时时会引发该类型(对应于将ETIMEDOUT值设置为ETIMEDOUT值)。但是,我不建议您自己提高此值,因为它的特定目的是响应操作系统返回的超时而引发该值。在

正确使用signal.signal

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

发生这种情况是因为您的信号处理程序没有按照^{} package所期望的那样遵循信号处理程序函数的定义(这些文档用于Python3,但与Python2相同):

signal.signal(signum, handler)

Set the handler for signal signalnum to the function handler... The handler is called with two arguments: the signal number and the current stack frame

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

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

更好的方法?使用socket.settimeout

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

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


TimeoutException最初是从哪里来的?在

很明显,你对这个的使用可能来自任何地方。但是,我注意到Selenium中有一个^{},它是一个广泛使用的Python库,用于自动化浏览器。它被广泛使用,与Selenium相关的examples/Q&A也很常见,因此如果您发现文档或示例使您相信这是标准库中存在的异常类型,而实际上它是特定于该库的类型,那么我不会感到惊讶。似乎与硒有关的任何内容都不适用于您当前的用例。在

相关问题