python 函数超时装饰器

##### 不关乎主线程还是子线程的超时装饰器
#-*-coding:utf8-*-
import os
import threading
import time

import sys


class KThread(threading.Thread):
    """A subclass of threading.Thread, with a kill()
    method.
    
    Come from:
    Kill a thread in Python: 
    http://mail.python.org/pipermail/python-list/2004-May/260937.html
    """
    def __init__(self, *args, **kwargs):
        threading.Thread.__init__(self, *args, **kwargs)
        self.killed = False

    def start(self):
        """Start the thread."""
        self.__run_backup = self.run
        self.run = self.__run      # Force the Thread to install our trace.
        threading.Thread.start(self)

    def __run(self):
        """Hacked run function, which installs the
        trace."""
        sys.settrace(self.globaltrace)
        self.__run_backup()
        self.run = self.__run_backup

    def globaltrace(self, frame, why, arg):
        if why == 'call':
          return self.localtrace
        else:
          return None

    def localtrace(self, frame, why, arg):
        if self.killed:
          if why == 'line':
            raise SystemExit()
        return self.localtrace

    def kill(self):
        self.killed = True
        
class Timeout(Exception):
    """function run timeout"""
class Timeout(Exception):
    """function run timeout"""
    
def timeout(seconds):
    """超时装饰器,指定超时时间
    若被装饰的方法在指定的时间内未返回,则抛出Timeout异常"""
    def timeout_decorator(func):
        """真正的装饰器"""
        
        def _new_func(oldfunc, result, oldfunc_args, oldfunc_kwargs):
            result.append(oldfunc(*oldfunc_args, **oldfunc_kwargs))
        
        def _(*args, **kwargs):
            result = []
            new_kwargs = { # create new args for _new_func, because we want to get the func return val to result list
                'oldfunc': func,
                'result': result,
                'oldfunc_args': args,
                'oldfunc_kwargs': kwargs
            }
            thd = KThread(target=_new_func, args=(), kwargs=new_kwargs)
            thd.start()
            thd.join(seconds)
            alive = thd.isAlive()
            thd.kill() # kill the child thread
            try:
                if alive:
                    raise Timeout(u'function run too long, timeout %d seconds.' % seconds)
                else:
                    return result[0]
            except:
                 print '------%s-----\n'%new_kwargs
                
        _.__name__ = func.__name__
        _.__doc__ = func.__doc__
        return _
    return timeout_decorator  


@timeout(8)

 

#简单函数超时装饰器,和简单类方法超时装饰器(限定liunx,主线程)
import signal
def handler(signum, frame):
    raise AssertionError

def timeout(arg=10): 
    def _deco(func):
        def __deco(self,*args,**kwargs):
            try:
                signal.signal(signal.SIGALRM, handler)
                signal.alarm(arg)
                ret=func(self,*args,**kwargs)
                signal.alarm(0)
                return ret
            except AssertionError:
                print("timeout,%s"%arg)

        return __deco
    return _deco

 

#-*-coding:utf8-*-

import time

import signal

 

def handler(signum, frame):

    raise AssertionError

 

def timeout(arg):

    def _deco(func):

        def __deco(*args,**kwargs):

            try:

                signal.signal(signal.SIGALRM, handler)

                signal.alarm(arg)

                func(*args,**kwargs)

                signal.alarm(0)

            except AssertionError:

                print "timeout,%s"%arg

 

        return __deco

    return _deco

@timeout(5)

def test(i=5):

    time.sleep(i)

    print "%d sleep time"%(i)

    return i

 

转载于:https://my.oschina.net/u/2367514/blog/668434

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值