【问题标题】:python: windows equivalent of SIGALRMpython:相当于SIGALRM的windows
【发布时间】:2012-01-15 06:22:40
【问题描述】:

我有这个装饰器:

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 中运行的最简单方法是什么?

【问题讨论】:

    标签: python windows signals alarm signal-handling


    【解决方案1】:

    它不是很漂亮,但我不得不以跨平台的方式做类似的事情,我想出了使用单独的线程。基于信号的系统并非在所有平台上都能可靠运行。

    这个类的使用可以封装在一个装饰器中,或者做成一个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()
    

    【讨论】:

    • 我似乎无法让上面的代码以我使用这个超时的方式工作 codepen.io/illsio/pen/oNbybRg 我用 t.evt.wait 尝试过,其中 t = Tiker(3.0) t.start() 但那不做这项工作。
    【解决方案2】:

    此答案仅适用于 Cygwin

    我发现这个超时装饰器代码也非常方便。 (我最初是在这个问题答案中找到的:How to limit execution time of a function call?

    为了让它在 Windows 上运行,我使用了随 Cygwin 一起安装的 Python。

    我运行 setup-x86_64.exe,然后从 Python 文件夹中选择 python3 包。 (或者,如果您更喜欢 Python 2,请使用 python 包。)

    为了将python3重命名为python2,我定义了别名

    alias python=python3
    

    来自 Cygwin 命令提示符。由于我不经常使用此功能,因此我可能不会将其放入 .bashrc 或其他任何内容中。

    相关问题: Python signal don't work even on Cygwin?

    【讨论】:

    • 有人能指出这个答案有什么问题吗?我自己没有看到任何问题。 (我是作者)
    • 你实际上并没有帮助。您的建议是一种偏转,而不是解决方案。
    • 问题询问“让这段代码在 Windows 中也能工作的最简单方法是什么?”我回答“为了让它在 Windows 上运行,我使用随 Cygwin 一起安装的 Python。”它对我有用的解决方案。
    • “它在 Cygwin 中工作”只是比“它在 Windows 主机上运行的 linux VM 上工作”稍有改进。这不是一个答案,它只是一种解决方法。
    猜你喜欢
    • 2010-10-12
    • 2021-05-26
    • 1970-01-01
    • 2017-12-08
    • 2011-05-09
    • 2010-10-18
    • 1970-01-01
    • 2016-05-08
    相关资源
    最近更新 更多