2011-12-07 3 views
7
の窓に相当

私は、このデコレータを持っている:のpython:SIGALRM

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のこのコードの動作を持ってする最も簡単な方法は何でしょうか?

答えて

8

それは非常にきれいではありませんが、私は、クロスプラットフォームな方法で似た何かをしなければならなかった、と私は別のスレッドを使用して思い付きました。信号ベースのシステムはすべてのプラットフォームで確実に動作しませんでした。このクラスの

使用はデコレータに包まれ、またはwithコンテキストハンドラに作ることができます。

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() 
0

このタイムアウトデコレータコードは非常に便利です。 (私はもともとこの質問の答えでそれを見つけた:How to limit execution time of a function call in Python)それはWindows上で動作させるために

を、私はCygwinのと一緒にインストールされるのPythonを使用しています。

私は、Pythonフォルダからpython3パッケージを選択し、セットアップ-x86_64.exeを実行します。 (または、あなたは、Python 2、pythonパッケージを好む場合。)

python2へのpython3の名前を変更するには、私はCygwinのコマンドプロンプトから別名

alias python=python3 

を定義します。私は非常に多くの場合、この機能を使用していないので、私はおそらくの.bashrcか何かに入れていないだろう。

関連質問: Python signal don't work even on Cygwin?

+0

誰かがこの答えが間違っているものを指摘してもらえますか?私はそれ自身で何の問題も見ません。 (私は著者です) –

関連する問題