Python 에서 스 레 드 Timeout 사용

2901 단어 PythonTimeoutUtils
Python 에 서 는 Timeout 에 대해 더 간편 하 게 사용 할 수 있 는 방법 이 있 습 니 다.즉,장식 기 를 사용 하 는 것 입 니 다.이 방식 은 sys 모듈 의 settrace 등 방법 으로 python 의 threading 류 를 재 구성 한 것 입 니 다.
#!/usr/bin/python
import threading
import sys
class KThread(threading.Thread):
    """Subclass of threading.Thread, with a kill() method."""
    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
        """Force the Thread to install our trace."""
        self.run = self.__run
        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

그 다음 에 timeout 장식 기 를 만 듭 니 다.이 장식 기 는 위 에 다시 실 린 KThread 를 이용 하여 시간 제한 을 실현 합 니 다.
def timeout(seconds):
    def timeout_decorator(func):
        def _new_func(oldfunc, result, oldfunc_args, oldfunc_kwargs):
            result.append(oldfunc(*oldfunc_args, **oldfunc_kwargs))
        def _(*args, **kwargs):
            result = []
            '''create new args for _new_funcbecause
               we want to get the func return val to result list
            '''
            new_kwargs = {
                '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()
            '''kill the child thread'''
            thd.kill()
            if alive:
                alert_exce = u'function timeout for [%d s].' % seconds
                raise Timeout(alert_exce)
            else:
                return result[0]
        _.__name__ = func.__name__
        _.__doc__ = func.__doc__
        return _
    return timeout_decorator

  이 방법 은 매우 간단 합 니 다.시간 초과 제어 가 필요 한 함수 앞에서@timeout(sec)장식 기 를 사용 하면 됩 니 다.
  그러나 이런 방법 은 비교적 뚜렷 한 결함 이 있다.본질 적 으로 함 수 를 다시 불 러 오 는 스 레 드 로 제어 하 는 것 이기 때문에 장식 기 가 추 가 된 함수 내부 에 스 레 드 나 서브 프로 세 스 등 복잡 한 구 조 를 사용 하면 이러한 스 레 드 와 서브 프로 세 스 는 시간 초과 통 제 를 받 을 수 없 기 때문에 외층 의 시간 초과 제어 가 무효 가 될 수 있다.

좋은 웹페이지 즐겨찾기