Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/359.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 超时功能,如果完成时间过长_Python - Fatal编程技术网

Python 超时功能,如果完成时间过长

Python 超时功能,如果完成时间过长,python,Python,我有一个shell脚本,它循环遍历一个文本文件,其中包含我想要访问的URL:s并截图 所有这些都很简单。该脚本初始化一个类,该类在运行时创建列表中每个站点的屏幕截图。有些站点需要很长很长时间才能加载,有些站点可能根本无法加载。因此,我想将screengrabber函数包装在一个超时脚本中,如果它不能在10秒内完成,则使函数返回False 我对最简单的解决方案很满意,也许设置一个异步计时器,10秒后不管函数内部实际发生了什么都会返回False?操作超时的过程在的文档中描述 其基本思想是使用信号处理

我有一个shell脚本,它循环遍历一个文本文件,其中包含我想要访问的URL:s并截图

所有这些都很简单。该脚本初始化一个类,该类在运行时创建列表中每个站点的屏幕截图。有些站点需要很长很长时间才能加载,有些站点可能根本无法加载。因此,我想将screengrabber函数包装在一个超时脚本中,如果它不能在10秒内完成,则使函数返回
False


我对最简单的解决方案很满意,也许设置一个异步计时器,10秒后不管函数内部实际发生了什么都会返回False?

操作超时的过程在的文档中描述

其基本思想是使用信号处理程序为某个时间间隔设置警报,并在计时器过期时引发异常

请注意,这只适用于UNIX

下面是一个创建装饰器的实现(将以下代码另存为
timeout.py

这将创建一个名为
@timeout
的修饰符,该修饰符可应用于任何长时间运行的函数

因此,在应用程序代码中,您可以像这样使用装饰器:

from timeout import timeout

# Timeout a long running function with the default expiry of 10 seconds.
@timeout
def long_running_function1():
    ...

# Timeout after 5 seconds
@timeout(5)
def long_running_function2():
    ...

# Timeout after 30 seconds, with the error "Connection timed out"
@timeout(30, os.strerror(errno.ETIMEDOUT))
def long_running_function3():
    ...

我使用
with
语句重写了David的答案,它允许您这样做:

with timeout(seconds=3):
    time.sleep(4)
这将引发超时错误

代码仍在使用
信号
,因此仅限UNIX:

import signal

class timeout:
    def __init__(self, seconds=1, error_message='Timeout'):
        self.seconds = seconds
        self.error_message = error_message
    def handle_timeout(self, signum, frame):
        raise TimeoutError(self.error_message)
    def __enter__(self):
        signal.signal(signal.SIGALRM, self.handle_timeout)
        signal.alarm(self.seconds)
    def __exit__(self, type, value, traceback):
        signal.alarm(0)

注意这不是线程安全的:如果使用多线程,信号将被随机线程捕获。但是对于单线程程序,这是最简单的解决方案。很好。此外,建议使用
@functools.wrapps(func)
FYI装饰函数
包装器
,以供参考,在第一个“@timeout”之后缺少包装。它应该是
@timeout()def…
@wim我认为它只能在主线程中使用,因为如果在工作线程中使用它,它将引发“ValueError:signal only works in main thread”。在使用线程时,有什么可行的替代方法呢?Python@timeout.timeout作为一个静态方法。然后,您可以很容易地在decorator和
with
语句之间进行选择。有趣的是,如果在
with Timeout(t)
上下文中引发了任何错误,则仍然会调用
\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu
,从而避免了由引发的
TimeOutError
而不是真正的错误引起的任何复杂情况。这是一个非常可爱的解决方案。有人能推荐一个可行的解决方案,像这样,在线程中工作吗?@Nick前段时间我创建了一个超时装饰器版本,它与浮动一起工作-适用于所有懒惰的人,他们喜欢使用库,而不是从StackOverflow复制+粘贴代码片段:
import signal

class timeout:
    def __init__(self, seconds=1, error_message='Timeout'):
        self.seconds = seconds
        self.error_message = error_message
    def handle_timeout(self, signum, frame):
        raise TimeoutError(self.error_message)
    def __enter__(self):
        signal.signal(signal.SIGALRM, self.handle_timeout)
        signal.alarm(self.seconds)
    def __exit__(self, type, value, traceback):
        signal.alarm(0)