title: Equivalent of setInterval in python
body: <p>I have recently posted a <a href="https://stackoverflow.com/questions/5177439/postponing-functions-in-python">question</a> about how to postpone execution of a function in Python (kind of equivalent to Javascript <code>setTimeout</code>) and it turns out to be a simple task using <code>threading.Timer</code> (well, simple as long as the function does not share state with other code, but that would create problems in any event-driven environment).</p>
  
  <p>Now I am trying to do better and emulate <code>setInterval</code>. For those who are not familiar with Javascript, <code>setInterval</code> allows to repeat a call to a function every x seconds, without blocking the execution of other code. I have created this example decorator:</p>
  
  <pre><code>import time, threading
  
  def setInterval(interval, times = -1):
      # This will be the actual decorator,
      # with fixed interval and times parameter
      def outer_wrap(function):
          # This will be the function to be
          # called
          def wrap(*args, **kwargs):
              # This is another function to be executed
              # in a different thread to simulate setInterval
              def inner_wrap():
                  i = 0
                  while i != times:
                      time.sleep(interval)
                      function(*args, **kwargs)
                      i += 1
              threading.Timer(0, inner_wrap).start()
          return wrap
      return outer_wrap
  </code></pre>
  
  <p>to be used as follows</p>
  
  <pre><code>@setInterval(1, 3)
  def foo(a):
      print(a)
  
  foo('bar')
  # Will print 'bar' 3 times with 1 second delays
  </code></pre>
  
  <p>and it seems to me it is working fine. My problem is that</p>
  
  <ul>
  <li>it seems overly complicated, and I fear I may have missed a simpler/better mechanism</li>
  <li>the decorator can be called without the second parameter, in which case it will go on forever. When I say foreover, I mean <strong>forever</strong> - even calling <code>sys.exit()</code> from the main thread will not stop it, nor will hitting <code>Ctrl+c</code>. The only way to stop it is to kill python process from the outside. I would like to be able to send a signal from the main thread that would stop the callback. But I am a beginner with threads - how can I communicate between them?</li>
  </ul>
  
  <p><strong>EDIT</strong> In case anyone wonders, this is the final version of the decorator, thanks to the help of jd</p>
  
  <pre><code>import threading
  
  def setInterval(interval, times = -1):
      # This will be the actual decorator,
      # with fixed interval and times parameter
      def outer_wrap(function):
          # This will be the function to be
          # called
          def wrap(*args, **kwargs):
              stop = threading.Event()
  
              # This is another function to be executed
              # in a different thread to simulate setInterval
              def inner_wrap():
                  i = 0
                  while i != times and not stop.isSet():
                      stop.wait(interval)
                      function(*args, **kwargs)
                      i += 1
  
              t = threading.Timer(0, inner_wrap)
              t.daemon = True
              t.start()
              return stop
          return wrap
      return outer_wrap
  </code></pre>
  
  <p>It can be used with a fixed amount of repetitions as above</p>
  
  <pre><code>@setInterval(1, 3)
  def foo(a):
      print(a)
  
  foo('bar')
  # Will print 'bar' 3 times with 1 second delays
  </code></pre>
  
  <p>or can be left to run until it receives a stop signal</p>
  
  <pre><code>import time
  
  @setInterval(1)
  def foo(a):
      print(a)
  
  stopper = foo('bar')
  
  time.sleep(5)
  stopper.set()
  # It will stop here, after printing 'bar' 5 times.
  </code></pre>