Python 如何在特定时间执行程序

Python 如何在特定时间执行程序,python,group-by,Python,Group By,我有一个程序,我需要在一定的时间间隔内执行。例如,我可能希望它每五分钟执行一次。我有几个与多个终端节点设备通信的协调器。下面的代码位于“协调员”选项卡上。我需要它,以便如果间隔设置为5,那么它将运行并记录信息,例如:9:05、9:10、9:15、9:20、9:25等。到目前为止,我拥有的代码如下: if __name__ == '__main__': while True: try: r = json.read(rqst_command())

我有一个程序,我需要在一定的时间间隔内执行。例如,我可能希望它每五分钟执行一次。我有几个与多个终端节点设备通信的协调器。下面的代码位于“协调员”选项卡上。我需要它,以便如果
间隔设置为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分钟标记上,则睡眠片刻,然后再次检查。我已经基本完成了代码。但是,我在运行程序时遇到以下错误:
'builtin\u function\u或\u method'对象没有属性'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

如果您使用Linux,您可能需要设置一个在特定时间间隔内运行脚本的程序。

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

第一种也是最好的方法是使用操作系统的任务调度器(Windows中的任务调度器,Linux中的cron
)。这些工具的开发人员可能预料到的问题比您想象的要多,您不必自己编写的代码节省了时间,也可能节省了bug


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

正如其他人所指出的,已经有了像cron这样的随时可用的作业/任务调度器。你可以直接使用它们。但您也可以用Python实现自己的简单解决方案,这很好。你只要用正确的方法就行了。您的方法的根本问题是,您在操作之间的某个时间间隔内睡眠,并且没有定期检查系统时间。在您的方法中,操作的持续时间是时间度量的误差。每个动作都会导致这个错误。您需要有一个没有此错误的时间参考,即系统时间

实现示例: 例如,考虑一下,一秒钟的精度对你来说已经足够好了。然后在循环中每秒检查系统时间。这可以通过
时间安全地实现。睡眠(1)
。如果系统时间比
last\u action\u execution\u time
晚5分钟(您显然已将其存储在某处),则将当前时间存储为
last\u action\u execution\u time
并执行该操作。只要此操作确实持续不到5分钟,下一次执行将在
last\u action\u execution\u time+5分钟执行,只有一个非常小的错误。最重要的是,此错误在运行时不会随着执行次数的增加而增加


对于一个基于Python的坚如磐石的解决方案,您还应该看看。

我假设您希望在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
那么:

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
为true时:
尝试:
start=time.time()#在开始执行之前保存开始时间
r=json.read(rqst_命令())
间隔=r.get('intvl')
collect\u time=r.get('c\u time')
command=r.get('cmd')
start_time=datetime.now()
发送\统计信息(命令\节点(命令、收集\时间))
end_time=datetime.now()
睡眠时间=间隔-(结束时间-开始时间)

下面的代码最终解决了我的问题。现在,无论时间间隔是什么,它都将始终使用
datetime
,从每小时的开始开始,并按时间间隔递增。因此,如果间隔为5,则
datetime
显示为例如:9:00:00、9:05:00、9:10:00、9:15:00、9:20:00、9:25:00等。如果间隔为3,则
日期时间将显示为例如: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

您是否考虑过使用像cron这样的任务调度器?在操作系统级别上处理它是否会更容易,比如设置一个任务调度程序?编辑:小天狼星打败了我!运行该程序的协调器实际上是一个Digi ConenctPort X4。我不认为cron是一个选项。你必须向我们展示完整的回溯,拜托。我如何获得完整的回溯?我正在使用notepad++编辑python,并在硬件上运行它。我正在使用的设备上没有嵌入python.cron。