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

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

新規登録して質問してみよう
ただいま回答率
85.48%
Python 3.x

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

Q&A

解決済

2回答

5709閲覧

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

TaikiNamioka

総合スコア24

Python 3.x

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

0グッド

0クリップ

投稿2018/04/23 04:51

編集2018/04/23 08:48

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

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を複数実装する場合、どのような処理を行えばいいのでしょうか?

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

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

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

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

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

Python

1# -*- coding: utf-8 -*- 2from datetime import datetime, timedelta 3import time 4# 5import schedule 6 7 8def job(): 9 nowDate = datetime.now() 10 print(nowDate) 11 12 13def entry(): 14 schedule.every(1).minutes.do(job) 15 #schedule.every(15).minutes.do(job) 16 return schedule.CancelJob 17 18 19def main(): 20 run_date = datetime.now() + timedelta(minutes=1) 21 schedule.every().day.at(run_date.strftime("%H:%M")).do(entry) 22 while True: 23 schedule.run_pending() 24 time.sleep(1) 25 26 27if __name__ == "__main__": 28 main() 29

投稿2018/04/23 09:05

umyu

総合スコア5846

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

KSwordOfHaste

2018/04/23 09:35

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

2018/04/23 13:53

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

0

ベストアンサー

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

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

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

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

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

scheduleを複数起動には・・・

Python

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

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


余談:

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

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

投稿2018/04/23 08:09

KSwordOfHaste

総合スコア18394

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

TaikiNamioka

2018/04/23 08:46

詳しくご回答いただきありがとうございます! 15分単位での起動方法も承知致しました。 誤差の部分はやはり仕方がない部分になるのですね。 質問がわかりにくくて申し訳ないのですが、 実行時間を各分の00秒に実行する場合はどのような処理を行うとよろしいでしょうか? おっしゃられていた通り、コンマ秒の誤差は気にしないようにします。
KSwordOfHaste

2018/04/23 08:58

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

2018/04/23 13:55

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問