質問: "__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を複数実装する場合、どのような処理を行えばいいのでしょうか?
回答: ご質問にある実験結果を見ますにそこそこの精度で起動してくれているように見えます。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のプログラムを作る」というなら、そんな点も頭の片隅においておくとよいかも知れません。