我有这个装饰:
def timed_out(timeout): def decorate(f): if not hasattr(signal, "SIGALRM"): return f def handler(signum, frame): raise TimedOutExc() @functools.wraps(f) def new_f(*args, **kwargs): old = signal.signal(signal.SIGALRM, handler) signal.alarm(timeout) try: result = f(*args, **kwargs) finally: signal.signal(signal.SIGALRM, old) signal.alarm(0) return result new_f.func_name = f.func_name return new_f return decorate
代码只能在Linux上做任何事情,但是,在Windows上,没有SIGALRM
。 让这个代码在Windows中工作最简单的方法是什么?
这不是很漂亮,但我必须以跨平台的方式做类似的事情,而且我想出了一个单独的线程。 基于信号的系统不能在所有平台上可靠地工作。
这个类的使用可以包装在一个装饰器中,或者with
上下文处理器一起构成。
因人而异。
#!/usr/bin/env python2.7 import time, threading class Ticker(threading.Thread): """A very simple thread that merely blocks for :attr:`interval` and sets a :class:`threading.Event` when the :attr:`interval` has elapsed. It then waits for the caller to unset this event before looping again. Example use:: t = Ticker(1.0) # make a ticker t.start() # start the ticker in a new thread try: while t.evt.wait(): # hang out til the time has elapsed t.evt.clear() # tell the ticker to loop again print time.time(), "FIRING!" except: t.stop() # tell the thread to stop t.join() # wait til the thread actually dies """ # SIGALRM based timing proved to be unreliable on various python installs, # so we use a simple thread that blocks on sleep and sets a threading.Event # when the timer expires, it does this forever. def __init__(self, interval): super(Ticker, self).__init__() self.interval = interval self.evt = threading.Event() self.evt.clear() self.should_run = threading.Event() self.should_run.set() def stop(self): """Stop the this thread. You probably want to call :meth:`join` immediately afterwards """ self.should_run.clear() def consume(self): was_set = self.evt.is_set() if was_set: self.evt.clear() return was_set def run(self): """The internal main method of this thread. Block for :attr:`interval` seconds before setting :attr:`Ticker.evt` .. warning:: Do not call this directly! Instead call :meth:`start`. """ while self.should_run.is_set(): time.sleep(self.interval) self.evt.set()
我发现这个超时装饰器代码也非常方便。 (我最初在这个问题中发现它的答案: 如何限制在Python中的函数调用的执行时间 )
为了使它在Windows上工作,我使用了与Cygwin一起安装的Python。
我运行setup-x86_64.exe,然后从Python文件夹中选择python3
包。 (或者,如果你更喜欢Python 2, python
包。)
为了将python3重命名为python2,我定义了别名
alias python=python3
从Cygwin命令提示符。 因为我不经常使用这个功能,所以我可能不会把它放到.bashrc或者任何东西中。
相关问题: 即使在Cygwin上,Python信号也不起作用?