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

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

新規登録して質問してみよう
ただいま回答率
85.51%
Raspberry Pi

Raspberry Piは、ラズベリーパイ財団が開発した、名刺サイズのLinuxコンピュータです。 学校で基本的なコンピュータ科学の教育を促進することを意図しています。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

Q&A

解決済

2回答

1332閲覧

pythonのschedを使って指定時間に関数を実行させたい_その3

morutemu

総合スコア45

Raspberry Pi

Raspberry Piは、ラズベリーパイ財団が開発した、名刺サイズのLinuxコンピュータです。 学校で基本的なコンピュータ科学の教育を促進することを意図しています。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

0グッド

1クリップ

投稿2018/04/14 14:05

raspberry piでゴミの日をお知らせするプログラムを作りたいと
考えているのですが、時間になる前に(実行した瞬間に)what_garbage_day関数が
実行されてしまします。
そして、pythonコードだけで、(外部プログラムを使わないで)スケジュール実行される
このプログラムを何とかしたいのですが、どうしたらよいでしょうか?

python

1#!/usr/bin/env python 2# -*- coding: utf-8 -*- 3 4# ++++ モジュール ++++ 5import threading 6from datetime import datetime 7import sched 8import time 9 10# ++++ グローバル変数 +++++ 11call_time = "22:22:05" 12 13# ++++ 関数 +++++ 14class GarbageDayReminder: 15 def what_garbage_day(self): 16 print("今日は何のゴミの日") 17 18 # 指定時間に動作する関数 19 def specified_time(self): 20 # 変数 21 format_day = "%Y/%m/%d-" 22 format_time = "%H:%M:%S" 23 24 # format_timeだと日付が1990-1-1になるため現在の日付を代入する 25 now = datetime.now() 26 now_date = now.strftime(format_day) 27 28 # 指定時間を代入する 29 run = datetime.strptime(now_date + call_time, format_day + format_time) 30 run = int(time.mktime(run.utctimetuple())) 31 32 # スケジューラー 33 scheduler = sched.scheduler(time.time, time.sleep) 34 35 # 実行される関数を指定 36 scheduler.enterabs(run, 1, self.what_garbage_day) 37 scheduler.run() 38 39 # ++++ 動作 +++++ 40if __name__ == '__main__': 41 # GarbageDayReminderをインスタンス化 42 garbageDayReminder = GarbageDayReminder() 43 44 # スレッドで指定時間動作関数を動かす 45 t = threading.Thread(target = garbageDayReminder.specified_time) 46 t.start() 47 48 print("スレッド動作確認用")

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

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

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

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

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

morutemu

2018/04/16 03:37

いえ、問題は無いのですが、今後Linux以外でも使えるプログラムとしても見てみたくなり、できる限りpython内で話が完結出来たらいいなと思いまして、もう一度投稿してみました。申し訳ないです。
umyu

2018/04/16 15:42

最終的にやりたいことはなんですか?このプログラムを動かしたいだけですか?
shogiOtakku

2018/04/17 12:34

できる限りpython内で話が完結出来たらいいということであればscheduleモジュールでも問題ないと思います。
guest

回答2

0

時間になる前に(実行した瞬間に)what_garbage_day関数が実行されてしまします。

スケジュールした時間がすでに過ぎていないか確認しましょう。
もし、すでに過ぎていたら次の日のゴミを出す時間をwhat_garbage_day関数が呼び出されるように実装します。

pythonコードだけで、(外部プログラムを使わないで)スケジュール実行されるこのプログラムを何とかしたい

cronを使わないでということだと思いますが、その場合は前の回答者様が実装されている通り、what_garbage_dayの中で再度schedを使って再度what_garbage_day関数が呼び出されるように実装することになります。

投稿2018/04/17 12:42

shogiOtakku

総合スコア123

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

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

0

ベストアンサー

以下のコードでどうでしょうか。

Python

1#!/usr/bin/env python 2# -*- coding: utf-8 -*- 3 4# ++++ モジュール ++++ 5from threading import Thread 6from datetime import datetime, timedelta 7from sched import scheduler 8import time 9 10 11class GarbageDayReminder(object): 12 def __init__(self): 13 self.scheduler = scheduler(time.time, time.sleep) 14 # 3秒間隔 15 self.interval = timedelta(seconds=3) 16 # 1日間隔 17 #self.interval = timedelta(days=1) 18 19 def what_garbage_day(self): 20 """ 21 指定時間に動作する関数 22 """ 23 print("今日は何のゴミの日") 24 # 次のスケジュールを登録 25 self.scheduler.enter(self.interval.total_seconds(), 1, self.what_garbage_day) 26 #print(self.scheduler.queue) 27 28 def specified_time(self): 29 """ 30 スケジューラーに予定を登録し実行する。 31 """ 32 now = datetime.now() 33 # call_time の設定 34 run = now.replace(hour=22, minute=12, second=30, microsecond=0) 35 if now > run: 36 # スケジュール登録時に時間が経過していたら次の日に 37 run += timedelta(days=1) 38 pass 39 print(f"実行予定時刻:{run}") 40 self.scheduler.enterabs(run.timestamp(), 1, self.what_garbage_day) 41 self.scheduler.run() 42 43 44def main() -> None: 45 # GarbageDayReminderをインスタンス化 46 garbageDayReminder = GarbageDayReminder() 47 # スレッドで指定時間動作関数を動かす 48 t = Thread(target=garbageDayReminder.specified_time) 49 t.start() 50 print("スレッド動作確認用") 51 52 53if __name__ == '__main__': 54 main() 55

◇参考情報
sched.scheduler.enter

上記コードはscheduler.enterを使っているため、指定時間の呼び出しがミリ秒単位で遅延し累積します。(※) ※what_garbage_day関数の処理に掛かる時間とタイマーの精度の問題です。 質問文の要件として、そこまで頻繁に呼び出さないタスクだと思われたためこの実装にしましたが。 問題があるのでしたら、scheduler.enterabsを使った形に修正してくださいな。

投稿2018/04/16 16:54

編集2018/04/17 13:21
umyu

総合スコア5846

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

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

morutemu

2018/04/20 03:21

プログラムまでうっていただき、 ありがとうございました! まだ、まだしっかりとは試せてないですが、 やってみます!
morutemu

2018/04/20 22:15

ちなみに累積しますというのは、 # 1日間隔 #self.interval = timedelta(days=1) とした場合、1日間隔でミリ秒が毎日少しずつ累積していくのですか?
umyu

2018/04/21 02:03

>morutemuさんへ はい、そうです。 質問文の「ソースコード」を3秒間隔はそのままに以下の2箇所変更して出力を確認してみてくださいな。 1,what_garbage_dayの#print(self.scheduler.queue) の行のコメントを外す。 2,run += timedelta(days=1)の行をコメントアウトする。
morutemu

2018/04/21 14:42

私の実行環境内では、0.0313338秒ずれるみたいですね。 これに関しては、そこまで高性能を目指しているわけではないので、全然十分です! そこままで考えていただき、ありがとうございました!!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.51%

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

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

質問する

関連した質問