在python脚本中的某些时间范围内完成任务

时间:2013-07-09 23:21:49

标签: python date python-2.7 time while-loop

正如您在下面看到的,我的脚本是我创建的副本,有人可以帮助我改进/修复我的currenttime任务。

基本上,在白天定期调用测试每3分钟+60秒,每个周期性循环,它应该执行以下任务:

  • 23:30:00至23:40:00之间的任何地方,它会将屏幕变为虚假
  • 在23:40:00到23:50:00之间的任何地方检查是否清除屏幕是否为假,如果是,则清除某些文件,然后立即将清除屏幕设置为false
  • 在23:50:00到01:30:00的任何地方,只是闲着,除了检查时间外什么都不做。

    from datetime import date, timedelta
    from sched import scheduler
    from time import time, sleep, strftime
    import random
    clearscreen = 0
    
    def periodically(runtime, intsmall, intlarge, function):
        global clearscreen
    
         ## Get current time
        currenttime = strftime('%H:%M:%S')
    
        ## while currenttime is anywhere between 23:40 and 23:50 then...
        while currenttime > '23:30:00' and currenttime < '23:40:00':
            ## Update time
            currenttime = strftime('%H:%M:%S')
            print ("""23:30:00 to 23:40:00 | %s""" % (currenttime))
            sleep(1)
    
            ## If clearscreen = false then...
            if clearscreen == False:
                ## Set clearscreen to true to enable the next part work and to disable this part until the next day.
                clearscreen = True
                print "changed to true"
    
        ## If currenttime is anywhere between 23:50 and 23:59 then...
        while currenttime > '23:40:00' and currenttime < '23:50:00':
            ## Update time
            currenttime = strftime('%H:%M:%S')
            print ("""23:40:00 to 23:50:00 | %s""" % (currenttime))
            sleep(1)
    
            if clearscreen == True:
                ## clear stuff here
                print "cleared"
                ## Change clearscreen to to stop it running
                clearscreen = False
                print "changed to false"
    
        ## Only allow run_periodically during 01:30 and 23:30
        if clearscreen == False:
            while currenttime > '23:50:00' and currenttime < '23:59:59':
                ## Update time
                currenttime = strftime('%H:%M:%S')
                print ("""23:50:00 to 23:59:59 | %s""" % (currenttime))
                sleep(1)
            while currenttime > '00:00:00' and currenttime < '01:30:00':
                ## Update time
                currenttime = strftime('%H:%M:%S')
                print ("""00:00:00 to 01:30:00 | %s""" % (currenttime))
                sleep(1)
    
        runtime += random.randrange(intsmall, intlarge)
        s.enter(runtime, 1, function, ())
        s.run()
    
    def test():
        print "test function"
    
    while True:
        periodically(180, -60, +60, test)
    

非常感谢任何帮助。

编辑@abarnert

关于循环,这是函数应该做的事情:

23:3x:xx - While loop initiated as currenttime fits the while loop's conditions (time is inbetween 23:30:00 and 23:40:00)
23:3x:xx - clearscreen is false, setting it to true.
23:3x:xx to 23:40:00 - currenttime is updated every 1 second(s)
23:40:01 - While loop ended as currenttime no longer fits the while loop's conditions (time is outside of 23:30:00 and 23:40:00)

23:40:01 - While loop initiated as currenttime fits the while loop's conditions (time is inbetween 23:40:00 and 23:50:00)
23:40:01 - clearscreen is true, doing some stuff and then changing clearscreen to false
23:40:01 to 23:50:00 - currenttime is updated every 1 second(s)
23:50:01 - While loop ended as currenttime no longer fits the while loop's conditions (time is outside of 23:40:00 and 23:50:00)

23:50:01 - While loop initiated as currenttime fits the while loop's conditions (time is inbetween 23:50:00 and 23:59:59)
23:50:01 to 23:59:59 - currenttime is updated every 1 second(s)
00:00:00 - While loop ended as currenttime no longer fits the while loop's conditions (time is outside of 23:50:00 and 23:59:59)

00:00:00 - While loop initiated as currenttime fits the while loop's conditions (time is inbetween 00:00:00 and 01:30:00)
00:00:00 and 01:30:00 - currenttime is updated every 1 second(s)
00:00:00 - While loop ended as currenttime no longer fits the while loop's conditions (time is outside of 00:00:00 and 01:30:00)

你提到我反复更新当前时间,然后打印,然后睡觉。我该如何解决这个“问题”?


关于global clearscreen我不确定你的意思; “你没有锁定它”


我正在运行Windows所以signal.setitemer是不行的,我还需要将某些值/变量存储在我的脚本的内存中,这样Windows上的预定任务就不合适了吗?

你使用sched模块构建了一个代码示例,但它不起作用,我无法弄清楚如何让它工作,而且它对我来说也相当混乱。我还在学习,而且相当混乱。

1 个答案:

答案 0 :(得分:3)

Python无法“忽略while循环”(除非你有一些其他条件)。但是如果while循环告诉Python循环0次,它就会完全正确。


首先,你有这个循环:

while currenttime > '23:30:00' and currenttime < '23:40:00':

......接着是这一个:

while currenttime > '23:40:00' and currenttime < '23:50:00':

想一想23:40:00会发生什么。它既不是在23:40之前也不是在23:40之后,所以在你进入它之前你将跳过第二个循环。

虽然我们正在讨论这些问题,但有两条注意事项:

  • 您可以在Python中编写'23:40:00' < currenttime < '23:50:00'
  • 您可以使用datetimetime个对象代替字符串来比较时间。

接下来,您反复执行此操作:

currenttime = strftime('%H:%M:%S')
print ("""23:40:00 to 23:50:00 | %s""" % (currenttime))
sleep(1)

这意味着currenttime实际上不是当前时间。通常是一秒钟之前。想想这对你边缘的循环条件有什么影响。

作为旁注,sleep(1)不能保证只睡一秒钟。如果您的计算机很忙,或者决定它想要进入低功耗模式,它可能会显着超过一秒钟。如果中断飞行,它可能会短于一秒钟。即使在最好的情况下,它通常会在一个方向或另一个方向上关闭半个时钟。所以,如果你需要这个能够正好发射600次,那么通常不会这样做。


与此同时,你有这个:

global clearscreen

显然,任何人都无法在当前代码中更改此内容,因此可能在您的实际代码中,您试图从另一个线程更改它。但你没有锁定它。因此,您很可能不会立即看到更改,甚至永远


编写调度程序比看起来要困难得多。这就是为什么你通常更好地使用现有的。选项包括:

  • stdlib sched模块。
  • stdlib threading.Timer
  • stdlib signal.setitemer。仅适用于具有真实信号的平台(意味着不是Windows),如果您使用线程或fork,则可能在某些平台上不适用。
  • ActiveState上有关PyPI / recipes的各种第三方模块,可以为您提供更好的Timer(例如,使用带有即将到来的作业队列的单个计时器线程,而不是每个作业的线程)。
  • 一个处理定时器的事件循环框架 - 虽然如果您只需要调度,这可能有点过分,如果您有其他理由使用Twisted或wx或PyGame或gevent,请让它进行调度。
  • 在任何Unix上运行script-cron的外部计时器,Mac上的LaunchServices和其他一些Unix,Windows上的计划任务等。可能不适合每秒运行一个任务,但是从你的评论中,它听起来像你的真正需要的是“能够每3分钟调用一次功能+ - 60秒。”

由于您特别询问了sched ......有两种方法:

  1. 立即制定一整天的日程安排,并反复拨打enterabs以填写当天的任务,再加上明天午夜运行的另一项任务,并做同样的事情。
  2. 编写一个函数,根据当前时间计算下一个和之后要安排的任务,并执行此操作。在实际工作之后调用该函数。
  3. 这是第一个看起来的样子:

    import sched
    import datetime
    import time
    
    s = sched.scheduler(time.time, time.sleep)
    
    def dotoday():
        now = datetime.date.now()
        stime = now.time()
    
        # Schedule "first" every 3 minutes from 22:00 to 22:57
        if stime < datetime.time(22, 0):
            stime = datetime.time(22, 0)
        while stime <= datetime.time(22, 57):
            s.enterabs(stime, 1, first, ())
            stime += datetime.timedelta(0, 180)
    
        # Schedule "second" every 3 minutes from 23:00 to 23:57
        stime = datetime.time(23, 0)
        while stime <= datetime.time(23, 57):
            s.enterabs(stime, 1, second, ())
            stime += datetime.timedelta(0, 180)
    
        # Schedule "dotoday" to run tomorrow
        midnight = now.replace(hour=0, minute=0, second=0)
        tomorrow = midnight + datetime.timedelta(1, 0)
        s.enterabs(tomorrow, 1, dotoday, ())
    
    dotoday()
    s.run()
    

    我使这个变得比必要的复杂一点,所以你可以在23:31:17开始它,它将在23:31:17,23:34:17等运行第一批任务等到23:33:00,23:36:00等等。