如何在Python中每60秒异步执行一个函数?

时间:2010-02-08 16:40:19

标签: python function asynchronous call

我想在Python上每60秒执行一次函数,但我不希望同时被阻止。

我该如何异步进行?

import threading
import time

def f():
    print("hello world")
    threading.Timer(3, f).start()

if __name__ == '__main__':
    f()    
    time.sleep(20)

使用此代码,函数f在20秒time.time内每3秒执行一次。 最后它给出了一个错误,我认为这是因为threading.timer还没有被取消。

如何取消?

提前致谢!

7 个答案:

答案 0 :(得分:95)

您可以尝试使用threading.Timer类:http://docs.python.org/library/threading.html#timer-objects

import threading

def f(f_stop):
    # do something here ...
    if not f_stop.is_set():
        # call f() again in 60 seconds
        threading.Timer(60, f, [f_stop]).start()

f_stop = threading.Event()
# start calling f now and every 60 sec thereafter
f(f_stop)

# stop the thread when needed
#f_stop.set()

答案 1 :(得分:2)

最简单的方法是创建一个每60秒运行一次的后台线程。一个简单的实现是:

class BackgroundTimer(Thread):   
   def run(self):
      while 1:
        Time.sleep(60)
        # do something


# ... SNIP ...
# Inside your main thread
# ... SNIP ...

timer = BackgroundTimer()
timer.start()

显然,如果“做某事”需要很长时间,你需要在睡眠声明中适应它。但这可以作为一个很好的近似值。

答案 2 :(得分:2)

这取决于你实际上想要做的事情。线程是最常用和最不受欢迎的方式;你应该知道使用它时线程的问题:并非所有(非Python)代码都允许同时从多个线程进行访问,线程之间的通信应该使用线程安全的数据结构来完成,比如Queue.Queue,你赢了“能够从它外部中断线程,并在线程仍在运行时终止程序可能导致挂起的解释器或虚假的回溯。

通常有一种更简单的方法。如果您在GUI程序中执行此操作,请使用GUI库的计时器或事件功能。所有的GUI都有这个。同样,如果您正在使用其他事件系统,如Twisted或其他服务器进程模型,您应该能够挂钩到主事件循环,以使其定期调用您的函数。非线程方法会导致程序在函数挂起时被阻止,但不会在函数调用之间被阻止。

答案 3 :(得分:2)

我用Google搜索并找到了Python circuits框架,这样就可以等待 对于特定事件。

电路的.callEvent(self, event, *channels)方法包含一个fire和suspend-until-response功能,文档说:

  

将给定事件触发到指定通道并暂停执行   直到它被派遣。此方法只能作为调用方法   在处理程序的最高执行级别上的yield的参数(例如   “yield self.callEvent(event)”)。它有效地创造和回报   主循环将调用的生成器,直到事件发生   被派遣(见:func:circuits.core.handlers.handler)。

我希望你发现它像我一样有用:) ./regards

答案 4 :(得分:1)

如果你想在时钟"上调用方法" (例如,每小时小时),您可以将以下想法与您选择的任何线程机制集成:

import time

def wait(n):
    '''Wait until the next increment of n seconds'''
    x = time.time()
    time.sleep(n-(x%n))
    print time.asctime()

答案 5 :(得分:1)

我认为重复运行线程的正确方法是下一步:

import threading
import time

def f():
    print("hello world")  # your code here
    myThread.run()

if __name__ == '__main__':
    myThread = threading.Timer(3, f)  # timer is set to 3 seconds
    myThread.start()
    time.sleep(10)  # it can be loop or other time consuming code here
    if myThread.is_alive():
        myThread.cancel()

使用此代码,函数f在10秒time.sleep(10)内每3秒执行一次。最后,线程的运行被取消。

答案 6 :(得分:0)

为什么不创建专用线程,在其中放置一个简单的睡眠循环:

#!/usr/bin/env python
import time
while True:
   # Your code here
   time.sleep(60)