在python脚本中的特定时间段内完成任务 [英] Complete a task during certain time frames within a python script

查看:117
本文介绍了在python脚本中的特定时间段内完成任务的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

As you can see below here is a copy of my script what I've created, could someone help me improve/fix my currenttime tasks.

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

Basically, during the day periodically calls test every 3 mins +- 60 seconds each periodically cycle it is supposed to do the follow tasks:


  • 在23:30:00到23:40:00期间的任何地方,它将清除屏幕为假

  • 在23:40:00到23:50期间的任何地方: 00它检查clearscreen是否为false,如果为false,则清除某些文件,然后立即将clearscreen设置为false

  • 在23:50:00到01:30期间的任何地方: 00它只是闲着,只检查时间。

  • Anywhere during 23:30:00 to 23:40:00 it turns clearscreen to false
  • Anywhere during 23:40:00 to 23:50:00 it checks if clearscreen is false and if it is then it clears certain files and then it immediately sets clearscreen to false
  • Anywhere during 23:50:00 to 01:30:00 it just idles, doing nothing other than checking the time.

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)


任何帮助将不胜感激。

关于循环,这是函数应该执行的操作:

In regards to the loops this is what the function is supposed to be doing:

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)






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


You mention that I repeatedly update currenttime, then print, then sleep. How would I get around this "problem"?

关于全局清除屏幕 code>我不确定你的意思; 您没有锁

In regards to the global clearscreen I am unsure what you mean by; "you don't have a lock on it"

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

I'm running Windows so signal.setitemer is a no go and also I need certain values/variables to be stored in memory for my script so scheduled tasks on windows won't be appropriate correct?

您构建了一个示例代码使用 sched 模块,但是它不起作用,我无法弄清楚如何使其工作,而且这也让我感到困惑。我仍在学习,这相当令人困惑。

You built an example bit of code using the sched module but it doesn't work and I am unable to work out how to get it working, plus it's also rather confusing for me. I'm still learning and it's rather confusing.

推荐答案

Python不可能忽略while循环(除非您拥有他们之外的一些其他情况)。但是,如果while循环告诉Python循环0次,它将做到这一点。

There's no way Python can "ignore the while loops" (unless you have some other condition outside of them). But if the while loop tells Python to loop 0 times, it will do exactly that.

首先,您已经此循环:

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:00之前也不在之后,因此您甚至无需进入第二个循环。

Think about what happens at 23:40:00. It's neither before nor after 23:40:00, so you'll skip the second loop before you even get into it.

虽然我们在两个侧面这些行上的注释:

While we're at it, two side notes on these lines:


  • 您可以只写 '23:40:00'<当前时间<在Python中为'23:50:00'

  • 您可以使用 datetime time 对象而不是字符串来比较时间。

  • You can just write '23:40:00' < currenttime < '23:50:00' in Python.
  • You can use datetime or time objects instead of strings to compare times.

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

Next, you repeatedly do this:

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

这意味着 currenttime 实际上从来不是当前时间。通常是一秒钟前。考虑一下对边缘处的循环条件有什么影响。

This means that currenttime is never actually the current time. It's usually a second ago. Think about what that does to your loop conditions at the edges.

作为补充, sleep(1)不能保证精确地睡一秒钟。如果您的计算机很忙,或者决定要进入低功耗模式,则它的运行时间可能长于一秒钟。如果中断不断,则可能会短于一秒钟。即使在最好的情况下,它通常也会在一个方向或另一个方向上相差半个小时。因此,如果您需要精确地发射600次,通常就不会这样做。

As a side note, sleep(1) isn't guaranteed to sleep exactly one second. If your computer is busy, or decides it wants to go into low-power mode, it can go significantly longer than a second. If interrupts are flying, it can go shorter than a second. Even in the best case, it'll often by off by half a clock tick in one direction or the other. So, if you need this to fire exactly 600 times, it's generally not going to do that.

同时,您ve

global clearscreen

显然,没有人可以在您当前的代码中更改它,因此,大概在您的真实代码中,您试图从另一个线程更改它。但是您没有锁定。因此,您极有可能不会立即看到更改,甚至不会 ever

Obviously there's no way anyone can ever change this in your current code, so presumably in your real code you're attempting to change it from another thread. But you don't have a lock on it. So, it's perfectly possible that you will not see a change immediately, or even ever.

编写调度程序比看起来困难得多。因此,通常最好使用现有的设备。选项包括:

Writing schedulers is a lot harder than it looks. That's why you're usually better off using an existing one. Options include:


  • stdlib sched 模块。

  • stdlib threading.Timer

  • stdlib signal.setitemer 。仅在具有真实信号的平台上(不是Windows),如果使用线程或 fork ,则在某些平台上可能不合适。

  • PyPI上的各种第三方模块/ ActiveState上的食谱可为您提供更好的 Timer (例如,使用单个计时器线程

  • 一个处理计时器的事件循环框架-尽管如果只需要调度,如果有的话,这可能会过大使用Twisted或wx或PyGame或gevent的其他原因,请让其进行调度。

  • 运行脚本的外部计时器-在任何Unix上为cron,在Mac和其他某些Unix上为LaunchServices, Windows上的计划任务,等等。可能不适合每秒运行一次任务,但是从您的评论中看来,您的真正需求是能够每3分钟+-60秒调用一次函数。

  • The stdlib sched module.
  • The stdlib threading.Timer.
  • The stdlib signal.setitemer. Only on platforms with real signals (meaning not Windows), and possibly not appropriate on some platforms if you're using threads or fork.
  • Various third-party modules on PyPI/recipes on ActiveState that give you a better Timer (e.g., using a single timer thread with a queue of upcoming jobs, rather than a thread for each job).
  • An event loop framework that handles timers—although this is probably overkill if scheduling is all you need, if you have some other reason to use Twisted or wx or PyGame or gevent, let it do the scheduling.
  • An external timer that runs your script—cron on any Unix, LaunchServices on Mac and some other Unixes, Scheduled Tasks on Windows, etc. Probably not appropriate for running a task every second, but from your comments, it sounds like your real need is "to be able to call a function every 3 mins +- 60 seconds."

因为您专门询问过 sched ...有两种方法:

Since you specifically asked about sched… There are two approaches:


  1. 立即建立整天的时间表并致电 enterabs 重复的y可以用当天的任务来完成任务,再加上明天明天午夜运行的又执行相同任务的任务。

  2. 编写一个根据当前时间计算出哪个任务的函数安排下一个和什么时间安排在实际工作之后调用该函数。

  1. Build the whole day's schedule at once and call enterabs repeatedly to fill it with the day's tasks, plus one more task that runs at midnight tomorrow and does the same thing.
  2. Write a function that figures out, based on the current time, which task to schedule next and when, and does so. Call that function after the actual work.

这是第一个函数的样子:

Here's what the first one looks like:

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等。

I made this a bit more complicated than necessary, so that you can start it at 23:31:17 and it will run the first batch of tasks at 23:31:17, 23:34:17, etc. instead of waiting until 23:33:00, 23:36:00, etc.

这篇关于在python脚本中的特定时间段内完成任务的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆