• python 自定义超时模块


    1. eventlet (简单好用,但要修改函数)
    
    import requests
    import time
    import eventlet
    
    eventlet.monkey_patch()  # 必须加这条代码
    
    try:
        # Dontla 20200421 超时将抛出异常
        with eventlet.Timeout(2, True):  # 设置超时时间为2秒
            time.sleep(4)
            r = requests.get("http://10.101.35.249/", verify=False)
            print('error')
        print('程序运行未超时!')
    except eventlet.timeout.Timeout:
    # except:   # (或,两种都行,注意不能用except Exception,因为Exception是异常基类,我们这个超时异常未包含在它里面)
        print('程序运行超时!')
    
    
    
    1. 装饰器(自己写),不用修改原来的函数
    
    from threading import Thread
    import time
    import inspect
    import ctypes
    import sys
    
    sys.setrecursionlimit(1000000) #不加不知道为啥出现递归错误
    
    class TimeoutException(Exception):
        pass
    
    
    def _async_raise(tid, exctype):
        """raises the exception, performs cleanup if needed"""
        tid = ctypes.c_long(tid)
        if not inspect.isclass(exctype):
            exctype = type(exctype)
        res = ctypes.pythonapi.PyThreadState_SetAsyncExc(tid, ctypes.py_object(exctype))
        if res == 0:
            raise ValueError("invalid thread id")
        elif res != 1:
            # """if it returns a number greater than one, you're in trouble,
            # and you should call it again with exc=NULL to revert the effect"""
            ctypes.pythonapi.PyThreadState_SetAsyncExc(tid, None)
            raise SystemError("PyThreadState_SetAsyncExc failed")
    
    
    def stop_thread(thread):
        _async_raise(thread.ident, SystemExit)
    
    
    def timelimited(timeout):
        def decorator(function):
            def decorator2(*args, **kwargs):
    
                class TimeLimited(Thread):
                    def __init__(self, _error=None, ):
                        Thread.__init__(self)
                        self._error = _error
    
                    def run(self):
                        try:
                            self.result = function(*args, **kwargs)
                        except Exception as e:
                            self._error = str(e)
    
                    def _stop(self):
                        if self.is_alive():
                            stop_thread(self)
    
                t = TimeLimited()
                t.start()
                t.join(timeout)
    
                if isinstance(t._error, TimeoutException):
                    t._stop()
                    raise TimeoutException('timeout for %s' % (repr(function)))
    
                if t.is_alive():
                    t._stop()
                    raise TimeoutException('timeout for %s' % (repr(function)))
    
                if t._error is None:
                    return t.result
    
            return decorator2
        return decorator
    
    
    
    @timelimited(5)  # 设置运行超时时间2S
    def fn_1(secs):
        time.sleep(secs)
        print('fn_1')
        return 'Finished without timeout'
    
    
    def do_something_after_timeout():
        print('Time out!')
    
    
    if __name__ == "__main__":
        try:
            print(fn_1(3))  # 设置函数执行3S
        except TimeoutException as e:
            print(str(e))
            do_something_after_timeout()
    
    
    
    1. 装饰器(开源),不用修改原来的函数
    # pip install func_timeout
    https://zhuanlan.zhihu.com/p/39743129
    
    import time
    from func_timeout import func_set_timeout
    from func_timeout import func_timeout, FunctionTimedOut
    
    
    @func_set_timeout(2)
    def task():
        while True:
            print('hello world')
            time.sleep(1)
    
    if __name__ == '__main__':
        try:
            task()
        except FunctionTimedOut:
            print("doit('arg1', 'arg2') could not complete within 5 seconds and was terminated.
    ")
        except Exception as e:
            pass
    
    
    1. 装饰器(os._exit(1)),不用修改原来的函数,os._exit(1)这里不好
    
    from functools import wraps
    import time
    import os
    from threading import Thread
    
    def set_time_limit(t):
        def auto_quit(t1):
            '''此为控制进程超时退出的线程函数'''
            time.sleep(t1)
            print("time out {}".format(t1))
            os._exit(1) #此函数专门用于线程控制主进程退出,有兴趣的可以看一下和sys.exit()的区别
        def decorator(f):
            '''此函数用于传入被装饰函数f'''
            @wraps(f)
            def wrapper(*args,**kwargs):
                '''装饰器内部遵循的逻辑是:
                1.auto_quit先执行完,进程结束
                2.被修饰函数f先执行完,auto_quit函数停止执行
                3.被修饰函数执行完,下面的代码才能运行
                '''
                t1=Thread(target=auto_quit,args=(t,))  #此处的t是set_time_limit函数的形参,是auto_quit函数的实参
                t2=Thread(target=f,args=args,kwargs=kwargs)
                t1.setDaemon(True) #满足第2点
                t1.start()
                t2.start()
                t2.join() #满足第3点
            return wrapper
        return decorator
    
    
    @set_time_limit(3)
    def a(t):
        time.sleep(t)
        print("execuate finished")
    
    if __name__=="__main__":
        a(1)
        a(5)
        a(1) # 不会打印了
        print("执行完毕")
    
    
  • 相关阅读:
    【转载自酷壳】编程能力与编程年龄
    xcode中的nslog数据格式
    xcode 的 pch 预编译头文件
    获取App的Documents路径
    使用gdb调试app
    收集的一些OC知识点
    收集到的几篇看雪学院文章
    【转】iOS平台的应用程序调试与分析
    前端技术开发的一些建议
    UIImage的两种加载方式
  • 原文地址:https://www.cnblogs.com/amize/p/14251021.html
Copyright © 2020-2023  润新知