gpt4 book ai didi

python - python中setInterval的等价物

转载 作者:IT老高 更新时间:2023-10-28 20:55:16 29 4
gpt4 key购买 nike

我最近发布了 question关于如何推迟 Python 中函数的执行(类似于 Javascript setTimeout),结果证明这是一个使用 threading.Timer 的简单任务(嗯,简单如只要函数不与其他代码共享状态,但这会在任何事件驱动的环境中产生问题)。

现在我正在努力做得更好并模仿 setInterval。对于那些不熟悉 Javascript 的人,setInterval 允许每隔 x 秒重复一次对函数的调用,而不会阻塞其他代码的执行。我已经创建了这个示例装饰器:

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

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

  • 它似乎过于复杂,我担心我可能错过了一个更简单/更好的机制
  • 可以在没有第二个参数的情况下调用装饰器,在这种情况下它将永远持续下去。当我说永远,我的意思是 forever - 即使从主线程调用 sys.exit() 也不会停止它,也不会按 Ctrl+c。阻止它的唯一方法是从外部杀死 python 进程。我希望能够从主线程发送一个信号来停止回调。但我是线程的初学者 - 我如何在它们之间进行通信?

编辑如果有人想知道,这是装饰器的最终版本,感谢 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

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

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

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

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

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.

最佳答案

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

有几种方法可以与线程通信。要命令线程停止,您可以使用 threading.Event(),它有一个 wait() 方法,您可以使用该方法代替 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

关于python - python中setInterval的等价物,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5179467/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com