Python: Windows SIGALRM equivalent

I have this decorator:

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 

The code just does something on linux, although, like windows, there is no SIGALRM . What would be the easiest way to work with this code on Windows?

+7
source share
2 answers

It's not very pretty, but I needed to do something like this in a cross-platform way, and I came up with the idea of ​​using a separate thread. Signal-based systems did not work reliably on all platforms.

Use of this class can be completed in the decorator or made in the with context handler.

YMMV.

 #!/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() 
+8
source

I find this timeout decorator code very convenient. (I initially found the answer in this question: How to limit the execution time of a function call in Python )

To make it work on Windows, I use Python, which is installed with Cygwin.

Run setup-x86_64.exe, then select the python3 package from the Python folder. (Or, if you prefer Python 2, the python package.)

To rename python3 to python2, I define an alias

 alias python=python3 

from the command line of Cygwin. Since I don't use this feature very often, I probably won't put it in .bashrc or anything else.

Related question: Python signal not working even on Cygwin?

0
source

All Articles