等效于python中的setInterval [英] Equivalent of setInterval in python

查看:167
本文介绍了等效于python中的setInterval的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我最近发布了一个问题,有关如何推迟在Python中执行函数(相当于Javascript setTimeout),使用threading.Timer确实是一个简单的任务(好吧,只要函数不与其他代码共享状态,这就很简单,但是在任何事件驱动的环境中都会产生问题) ).

I have recently posted a question about how to postpone execution of a function in Python (kind of equivalent to Javascript setTimeout) and it turns out to be a simple task using threading.Timer (well, simple as long as the function does not share state with other code, but that would create problems in any event-driven environment).

现在,我正在尝试做得更好,并模仿setInterval.对于不熟悉Javascript的用户,setInterval允许每x秒重复调用一次函数,而不会阻止其他代码的执行.我创建了这个示例装饰器:

Now I am trying to do better and emulate setInterval. For those who are not familiar with Javascript, setInterval allows to repeat a call to a function every x seconds, without blocking the execution of other code. I have created this example decorator:

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

将按以下方式使用

@setInterval(1, 3)
def foo(a):
    print(a)

foo('bar')
# Will print 'bar' 3 times with 1 second delays

在我看来,它工作正常.我的问题是

and it seems to me it is working fine. My problem is that

  • 它似乎过于复杂,我担心我可能错过了一个更简单/更好的机制
  • 可以在没有第二个参数的情况下调用装饰器,在这种情况下它将永远持续下去.当我说到超越时,我的意思是永远-即使从主线程调用sys.exit()也不会停止它,也不会命中Ctrl+c.阻止它的唯一方法是从外部杀死python进程.我希望能够从主线程发送一个将停止回调的信号.但是我是线程的初学者-如何在线程之间进行通信?
  • it seems overly complicated, and I fear I may have missed a simpler/better mechanism
  • the decorator can be called without the second parameter, in which case it will go on forever. When I say foreover, I mean forever - even calling sys.exit() from the main thread will not stop it, nor will hitting Ctrl+c. 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?

编辑如果有人怀疑,这是装饰器的最终版本,这要感谢jd

EDIT In case anyone wonders, this is the final version of the decorator, thanks to the help of jd

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

它可以与上述的固定重复次数一起使用

It can be used with a fixed amount of repetitions as above

@setInterval(1, 3)
def foo(a):
    print(a)

foo('bar')
# Will print 'bar' 3 times with 1 second delays

或者可以一直运行直到收到停止信号

or can be left to run until it receives a stop signal

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.

推荐答案

您的解决方案对我来说很好.

Your solution looks fine to me.

有几种与线程通信的方法.要命令一个线程停止,可以使用threading.Event(),它具有一个可以使用的wait()方法而不是time.sleep().

There are several ways to communicate with threads. To order a thread to stop, you can use threading.Event(), which has a wait() method that you can use instead of time.sleep().

stop_event = threading.Event()
...
stop_event.wait(1.)
if stop_event.isSet():
    return
...

为使线程在程序终止时退出,请在调用start()之前将其daemon属性设置为True.这也适用于Timer()对象,因为它们是threading.Thread的子类.请参见 http://docs.python.org/library/threading.html#threading.Thread.daemon

For your thread to exit when the program is terminated, set its daemon attribute to True before calling start(). This applies to Timer() objects as well because they subclass threading.Thread. See http://docs.python.org/library/threading.html#threading.Thread.daemon

这篇关于等效于python中的setInterval的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆