python:相当于SIGALRM的windows

python: windows equivalent of SIGALRM

我有这个装饰:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
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上下文处理程序。

因人而异。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
#!/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,我定义了别名

1
alias python=python3

从Cygwin命令提示符。由于我不经常使用此功能,我可能不会将它放入.bashrc或任何东西。

相关问题:
Python信号甚至在Cygwin上都不起作用?