1

以下に示すように、これは私が作成したスクリプトのコピーです。誰かが私のcurrenttimeタスクを改善/修正するのを手伝ってくれませんか。

基本的に、日中は定期的に 3 分ごとに test を呼び出します +-60 秒ごとに、次のタスクを実行することになっています。

  • 23:30:00 から 23:40:00 の間のどこでも、clearscreen が false に変わります
  • 23:40:00 から 23:50:00 の間のどこでも、clearscreen が false かどうかをチェックし、そうである場合は特定のファイルをクリアし、すぐに clearscreen を 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)

あなたは、私が currenttime を繰り返し更新し、次に印刷し、次にスリープすると言いました。この「問題」をどのように回避しますか?


に関しては、global clearscreenあなたが何を意味するのかわかりません。「ロックがかかっていません」


私は Windows を実行しているので、signal.setitemer は使用できません。また、スクリプト用に特定の値/変数をメモリに格納する必要があるため、Windows でスケジュールされたタスクは適切ではありませんか?

モジュールを使用してサンプルコードを作成しましたschedが、機能しません。また、機能させる方法がわかりません。また、かなり混乱しています。私はまだ学んでいて、かなり混乱しています。

4

1 に答える 1

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:00 の前後ではないため、2 番目のループに入る前にスキップします。

ここで、これらの行に関する 2 つの補足事項を示します。

  • '23:40:00' < currenttime < '23:50:00'Pythonで書くだけです。
  • datetime文字列の代わりにorオブジェクトを使用timeして時間を比較できます。

次に、これを繰り返します。

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

これは、currenttime実際には現在の時刻ではないことを意味します。通常は 1 秒前です。エッジでのループ条件がどうなるかを考えてみてください。

ちなみに、sleep(1)正確に 1 秒間スリープすることは保証されていません。コンピューターがビジー状態の場合、または低電力モードに入る必要がある場合は、1 秒よりも大幅に長くなる可能性があります。割り込みが飛んでいる場合は、1 秒未満になることがあります。最良の場合でも、多くの場合、どちらかの方向に半クロック ティックずれることがよくあります。したがって、これを正確に 600 回実行する必要がある場合、通常はそうはなりません。


一方、あなたはこれを持っています:

global clearscreen

明らかに、現在のコードでこれを変更できる方法はありません。したがって、おそらく実際のコードでは、別のスレッドから変更しようとしています。しかし、あなたはそれをロックしていません。そのため、変更がすぐに表示されない、またはまったく表示されない可能性は十分にあります


スケジューラーを書くのは、見た目よりずっと難しいです。そのため、通常は既存のものを使用する方がよいでしょう。オプションは次のとおりです。

  • stdlibschedモジュール。
  • 標準ライブラリthreading.Timer.
  • 標準ライブラリsignal.setitemer. 実際のシグナルを備えたプラットフォーム (Windows ではないことを意味します) のみで、スレッドまたはfork.
  • PyPI のさまざまなサードパーティ モジュール/ActiveState のレシピにより、より良い結果が得られますTimer(たとえば、各ジョブのスレッドではなく、次のジョブのキューで単一のタイマー スレッドを使用するなど)。
  • タイマーを処理するイベント ループ フレームワーク — スケジューリングだけが必要な場合はおそらくやり過ぎですが、Twisted、wx、PyGame、または gevent を使用する他の理由がある場合は、スケジューリングを行います。
  • スクリプトを実行する外部タイマー — Unix の cron、Mac およびその他の Unix の LaunchServices、Windows の Scheduled Tasks など「3 分 +- 60 秒ごとに関数を呼び出せるようにする」

あなたが具体的に尋ねたのでsched… 2つのアプローチがあります:

  1. 1 日のスケジュールを一度enterabsに作成し、その日のタスクと、明日の午前 0 時に実行され、同じことを行うもう 1 つのタスクを入力するために繰り返し呼び出します。
  2. 現在の時刻に基づいて、次にどのタスクをいつスケジュールするかを計算し、実行する関数を作成します。実際の作業の後にその関数を呼び出します。

最初のものは次のようになります。

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:33:00、23:36:00など

于 2013-07-10T18:37:18.340 に答える