每N秒调用2个python函数



在.py脚本中,我有两个函数。其中一个应每5分钟调用一次,另一个应每隔4小时调用一次。然而,第二个函数在脚本运行时只运行一次,再也不会运行(而5分钟的函数运行良好(。

#!/usr/bin/env python
import threading
def five_min(): 
    threading.Timer(300, five_min).start()
    print("5 min")
def four_h():
    threading.Timer(14400, four_h).start()
    print("4 h")
five_min()
four_h()

这是整个代码,我正在Linux(树莓派(上运行

第页。S我认为问题可能是4_h函数被5_min函数打断了。

在再次调用threading.Timer().start()之前,four_hour函数可能引发异常

import threading
import logging
logger = logging.getLogger(__name__)
def five_min(): 
    t = threading.Timer(5, five_min).start()
    logger.info("5 min")
def four_hour():
    1/0  # <-- Raise an exception
    threading.Timer(4, four_hour).start()
    logger.info("4 h")
logging.basicConfig(level=logging.DEBUG,
                    format='[%(asctime)s %(threadName)s] %(message)s',
                    datefmt='%M:%S')
five_min()
four_hour()

产生

[57:54 MainThread] 5 min
Traceback (most recent call last):
  File "script.py", line 21, in <module>
    four_hour()
  File "script.py", line 12, in four_hour
    1/0
ZeroDivisionError: integer division or modulo by zero
[57:59 Thread-1] 5 min
[58:04 Thread-2] 5 min
...

(注意:我更改了延迟,这样脚本更容易测试对脚本的定性行为感到满意,您可以在欲望。(


注:正如克莱姆托伊所指出的只要不需要线程间或进程间通信,就可以更易于使用要调用的cron分别运行CCD_ 3和CCD_。如果你这样做需要进程间通信,使用cron可能仍然更好,但您应该必须以不同的方式构建代码,也许可以从数据库中读取学习以前全局变量的状态。

我还认为问题在于4_h((被其他函数中断。您可以在5_min中创建一个计数器var,然后从那里调用4_h((。

#!/usr/bin/env python
import threading
counter = 0
def 5_min(): 
    threading.Timer(300, 5_min).start()
    counter += 1
    if (counter == 48):
        counter = 0
        4_h()
    print("5 min")
def 4_h():
    ...

这可能不是最好的解决方案,但却是我所知道的最好的方案。

在我看来,在linux上规划任务的最佳方式是使用cron。如果您希望脚本将任务本身添加到linux crontab中,那么您应该查看python crontab包。

现在抛开语法不谈。我建议你这样做:

from threading import Timer
s = 0; m = 0
fivesec_timer = None
fourmin_timer = None
def fivesec ():
    global fivesec_timer, s
    print s, "seconds passed after start"
    s += 5
    fivesec_timer = Timer(5, fivesec)
    fivesec_timer.start()
def fourmin ():
    global fourmin_timer, m
    print m, "minutes passed after start"
    m += 4
    fourmin_timer = Timer(4*60, fourmin)
    fourmin_timer.start()
fivesec()
fourmin()
# Here some code and blocking code
# For instance:
raw_input()
fivesec_timer.cancel()
fourmin_timer.cancel()
This way, you can control your timers outside your functions.
Don't do Timer(...).start(), especialy not inside a function (local scope).
It should work fine, but you never know what and when garbage collector would clean up or something else occurs. You do not know how the _Timer() is implemented internally.
And you don't have a hard reference to the timer (in a var) all the time.
Mutual canceling out was probably caused by that, although this is clear speculation.
threading module is well tested, yet you experienced problems. Keep your code neat. Best to be sure.
Well, that is my view of the world. Someone will not agree. :D

相关内容

  • 没有找到相关文章

最新更新