如何在特定时间执行程序

时间:2012-08-30 13:50:17

标签: python group-by

我有一个程序,我需要在一定的时间间隔执行。例如,我可能希望它每五分钟执行一次。我有几个协调器与几个终端节点设备通信。以下代码在协调员身上。我需要它,以便如果interval设置为5,那么它运行并记录信息,例如: 9:05,9:10,9:15,9:20,9:25 等。到目前为止我的代码如下:

if __name__ == '__main__':
    while True:
        try:
            r = json.read(rqst_command())
            interval = r.get('intvl')
            collect_time = r.get('c_time')
            command = r.get('cmd')
            send_stats(cmd_nodes(command, collect_time))
            time.sleep(interval)
        except Exception, e:
            print e
            print "**Top Level Exception"
            pass

问题在于,如果我将间隔设置为 5分钟,则不会每5分钟记录一次。执行时间似乎慢慢增加。例如,上面的代码可以记录为 9:05:09,9:10:19,9:15:29,9:20:41,9:25:50 。程序运行所需的时间取决于节点通信的速度。

有没有人对我如何更改代码有任何想法,以便程序每5分钟执行一次?

修改/更新

我想我找到了解决问题的方法。我抓住当前datetime,然后检查它是否在5分钟标记处。如果是,则记录datetime并将其发送到send_stats功能。这样datetime将永远是我想要的。如果它不在5分钟标记,然后sleep一段时间,然后再次检查。我的代码大部分都已完成。但是,运行程序时出现以下错误: 'builtin_function_or_method' object has no attribute 'year'

我做错了什么?

这是我的新代码:

import os
import json
import datetime
from datetime import datetime
import urllib2
from urllib import urlencode
from socket import *
import time
import zigbee
import select

if __name__ == '__main__':
        while True:
            try:
                r = json.read(rqst_command())
                interval = r.get('intvl')
                collect_time = r.get('c_time')
                command = r.get('cmd')

                tempTest = True

                while tempTest == True:
                    start_time = datetime.now
                    compare_time = datetime(start_time.year, start_time.month, start_time.day, start_time.hour, 0, 0)
                    difff = int((start_time - compare_time).total_seconds() / 60)

                    if((difff % interval) == 0):
                        c_t = datetime(start_time.year, start_time.month, start_time.day, start_time.hour, start_time.minute, 0)
                        send_stats(cmd_nodes(command, collect_time), c_t)
                        tempTest = False
                    else:
                        time.sleep(30)              
            except Exception, e:
                print e
                print "**Top Level Exception"
                pass

6 个答案:

答案 0 :(得分:3)

以下代码最终解决了我的问题。现在无论间隔是多少,它始终会在每小时开始时使用datetime并按间隔递增。因此,如果间隔为5,则datetime显示为例如: 9:00:00,9:05:00,9:10:00,9:15:00,9:20 :00,9:25:00等。如果间隔为3,则datetime显示为例如: 5:00:00,5:03:00,5:06:00,5:09:00,5:12:00 ,5:15:00等等。协调器从端节点获取数据,然后将数据与datetime一起发送到远程服务器。

if __name__ == '__main__':
    last_minute = -1

    while True:
        try:
            r = json.read(rqst_command())
            print r
            command = r.get('cmd')
            interval = r.get('intvl')
            collect_time = r.get('c_time')

            tempTest = True

            while tempTest == True:
                start_time = datetime.now()
                s_minute = start_time.minute

                if(((s_minute % interval) == 0) and (s_minute != last_minute)):
                    tempTest = False
                    c_t = datetime(start_time.year, start_time.month, start_time.day, start_time.hour, start_time.minute, 0)
                    last_minute = c_t.minute

                    send_stats(cmd_nodes(command, collect_time), c_t)
                    time.sleep(1)
                else:
                    time.sleep(1)
        except Exception, e:
            print e
            print "**Top Level Exception"
            pass

答案 1 :(得分:2)

正如其他人所指出的,已经有像cron这样的现成作业/任务调度程序。你可以使用它们。但是你也可以在Python中实现自己的简单解决方案,这很好。你必须以正确的方式做到这一点。您的方法中的基本问题是您在操作之间睡眠一定时间间隔并且不定期检查系统时间。在您的方法中,操作的持续时间是您的时间测量的错误。这个错误总结了每个动作。您需要有一个没有此错误的时间参考,这是系统时间。

实施示例: 例如,考虑一秒精度对您来说足够好。然后在循环内每秒检查一次系统时间。这可以通过time.sleep(1)安全地实现。如果系统时间是例如比last_action_execution_time晚了5分钟(您显然存储在某处),将当前时间存储为last_action_execution_time并执行操作。只要此操作肯定持续不到5分钟,下一次执行将在last_action_execution_time + 5 min发生,只有非常小的错误。最重要的是,此错误在运行时期间不会随执行次数而增加。

对于基于Python的坚如磐石的解决方案,您还应该查看http://docs.python.org/library/sched.html

答案 2 :(得分:2)

怎么样:

while true:
    try:

        start=time.time() # save the beginning time before execution starts

        r = json.read(rqst_command())
        interval = r.get('intvl')
        collect_time = r.get('c_time')
        command = r.get('cmd')
        start_time = datetime.now()
        send_stats(cmd_nodes(command, collect_time))
        end_time = datetime.now()
        sleepy_time = interval - (end_time - start_time)

        while time.time() <= start + sleepy_time*60: #To wait until interval has ended note: I'm assuming sleepy_time is in minutes.
            pass

    except Exception, e:
    print e
    print "**Top Level Exception"
    pass

答案 3 :(得分:1)

如果您使用Linux,则可能需要设置cronjob以一定的时间间隔运行脚本。

答案 4 :(得分:1)

有两种方法可以做到这一点。

第一个也是最好的是使用您的操作系统的任务调度程序(Windows中的任务计划程序,Linux中的cron)。这些工具的开发人员可能预期会出现比您想象的更多的问题,而您自己不需要做的代码就是时间,并且可能会保存错误。

否则,您需要考虑脚本的执行时间。最简单的方法是不要为你的间隔睡觉(当你看到慢慢向前滑动时),你会根据你上次醒来和执行后计算下次你应该执行的时间,只在间隔时间内睡觉从现在到现在。

答案 5 :(得分:1)

我假设您想在Python中执行此操作而不依赖于任何其他系统。

您只需要考虑流程何时开始以及何时结束并相应地设置您的时间间隔。代码看起来像这样。

if __name__ == '__main__':
while True:
    try:
        r = json.read(rqst_command())
        interval = r.get('intvl')
        collect_time = r.get('c_time')
        command = r.get('cmd')
        start_time = datetime.now()
        send_stats(cmd_nodes(command, collect_time))
        end_time = datetime.now()
        sleepy_time = interval - (end_time - start_time)
        time.sleep(sleepy_time)
    except Exception, e:
        print e
        print "**Top Level Exception"
        pass