質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

90.77%

  • Python 3.x

    5349questions

    Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

【python】scheduleでのタスク実行について

解決済

回答 2

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 324

TaikiNamioka

score 10

下記のようなコードを書いて

def job():
    nowDate = datetime.now()
    print(nowDate)

def main():
    schedule.every(1).minutes.do(job)
    while True:
        schedule.run_pending()
        time.sleep(1)


if __name__ == "__main__":
    main()

12:00:00 実行
12:01:00 実行
...
12:10:00 実行
のように各分の00秒に実行を行うように実装する想定だったのですが、
(コンマ秒以下の誤差は気にしないです。)

2018-04-23 13:39:45.945200
2018-04-23 13:40:46.079436
2018-04-23 13:41:46.256876

のような実行結果になってしましました。

+1~3秒の誤差は大丈夫なのですが、
アドバイスをいただきたいです。

また15分ごとの秒が0秒近似値で15分ごとのタスク実行も考えているのですが、
scheduleを複数実装する場合、どのような処理を行えばいいのでしょうか?

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 2

checkベストアンサー

+2

ご質問にある実験結果を見ますにそこそこの精度で起動してくれているように見えます。sleepの時間間隔を測ると分かりますがもともとそれほど高い精度でsleepしているわけではありません。数十ミリ秒ぐらいの誤差は普通にあると思います。

scheduleはrun_pendingが呼び出されたタイミングで「時刻が到来しているハンドラーがあったら起動する」という考え方でできてます。つまりtime.sleepがどの程度の精度で動いてくれるかで時刻の精度が決まります。sleepの精度が高くはないので、そう厳密な間隔での起動は望めないと思います。

おそらく1秒程度の誤差は許容する必要があるのではないでしょうか?しかし0秒誤差を期待するのは無理と思います。

なるべく起動誤差を減らすなら1秒単位でsleepするのではなく0.1秒単位にするといった工夫をするとなんらかの効果があるかも知れません。しかし、分単位の定期処理に対して0.1秒単位でsleepしても詮無い気がします。計算機の定期処理にそれほどの精度を望まない方がよいのではないでしょうか。

もし起動タイミングが重要なら(例えばなんらかの変化を連続的に記録する目的なら)考え方を変えて「いつ起動されたかを記録しておき、各起動時刻を加味した集計計算をする」という考え方もあるかと思います。

scheduleを複数起動には・・・

schedule.every(1).minutes.do(job_a)
schedule.every(15).minutes.do(job_b)
...

のように好きなだけ登録してやればよいようです。


余談:

python(cpython)はリファレンスカウンターによるメモリー管理をしてくれます。javaのようにマーク&スイープのみのgcに比べると、うまく設計しさえすれば不要なメモリーが即座に解放され効率よく動いてくれると思います。しかし、循環参照を作ってしまうとリファレンスカウンター方式での開放が行えないため、ガベージコレクターがマーク&スイープを起動してくれるまで不要メモリーが開放されなくなると思います。

Webサーバーなど長時間動作させるプログラムについて、プロセスの消費メモリーが肥大化して調べるのに苦労したなんて記事を見かけたことがありますが、そういうことを調査するのは大変と思います。「X分ごとに何かするpythonのプログラムを作る」というなら、そんな点も頭の片隅においておくとよいかも知れません。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/04/23 17:46

    詳しくご回答いただきありがとうございます!
    15分単位での起動方法も承知致しました。

    誤差の部分はやはり仕方がない部分になるのですね。

    質問がわかりにくくて申し訳ないのですが、
    実行時間を各分の00秒に実行する場合はどのような処理を行うとよろしいでしょうか?
    おっしゃられていた通り、コンマ秒の誤差は気にしないようにします。

    キャンセル

  • 2018/04/23 17:58

    あ、00:01:00, 00:02:00, ...に行いたいという事ですか?それでしたら最初にwhileループに入る前に00秒になるまで0.01秒単位ぐらいで待つというのでどうでしょう。scheduleに「ちょうど何秒に起動して」という機能があるならいいのですがそれがあるかどうかまでリファレンスをみてはいませんのでわかりません。

    キャンセル

  • 2018/04/23 22:55

    ご回答ありがとうございます!
    ループに入る前に待つ実装でも良さそうですね!
    参考になりました!

    キャンセル

+2

多分、タスク実行時の秒数が揃っていないのが気になってらっしゃると思われたので、以下のコードでどうでしょうか?
15分間隔の方は、少し考えてもうまい方法を思いつきませんでした!

# -*- coding: utf-8 -*-
from datetime import datetime, timedelta
import time
#
import schedule


def job():
    nowDate = datetime.now()
    print(nowDate)


def entry():
    schedule.every(1).minutes.do(job)
    #schedule.every(15).minutes.do(job)
    return schedule.CancelJob


def main():
    run_date = datetime.now() + timedelta(minutes=1)
    schedule.every().day.at(run_date.strftime("%H:%M")).do(entry)
    while True:
        schedule.run_pending()
        time.sleep(1)


if __name__ == "__main__":
    main()

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/04/23 18:35

    なるほど!特定のパターンの時刻指定がこれでできるのですね!

    キャンセル

  • 2018/04/23 22:53

    ありがとうございます!
    試してみます!
    15分は応用すれば行けそうな気がします!

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 90.77%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る

  • Python 3.x

    5349questions

    Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。