4

我有一个程序需要在一定的时间间隔内执行。例如,我可能希望它每五分钟执行一次。我有几个与多个终端节点设备通信的协调器。下面的代码在协调器上。我需要它,以便如果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
4

6 回答 6

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
于 2012-09-01T01:50:17.660 回答
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

于 2012-08-30T13:57:13.083 回答
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
于 2012-08-31T21:06:36.037 回答
1

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

于 2012-08-30T13:51:57.333 回答
1

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

第一个也是最好的方法是使用操作系统的任务调度程序(Windows中的任务调度程序, cronLinux 中的任务调度程序)。这些工具的开发人员可能预料到的问题比您想象的要多,而且您不必自己编写代码可以节省时间和可能的错误。

否则,您需要考虑脚本的执行时间。最简单的方法是不要在您的时间间隔内休眠(正如您所看到的那样缓慢向前滑动),您将根据您上次醒来的时间和执行后计算下一次执行的时间,仅在该时间间隔内休眠现在和那时之间。

于 2012-08-30T13:55:53.307 回答
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
于 2012-08-30T14:04:43.663 回答