前提・実現したいこと
※Python学習を始めたばかりです。
マルチスレッドそれぞれで定期処理をするプログラムをいろいろ試してみたくて書いたソースです。
作成した内容では、suchedule_event_communicateとsuchedule_event_run_print_helloの
スレッドを立ち上げています。
それぞれで、3秒に一回時刻を表示、5秒に一回"HELLO!!!"を表示(ただし、処理の途中で10秒間待機させる)という内容になっています。
発生している問題・エラーメッセージ
下記のソースを実行すると、以下のメッセージのように、
同じ時刻で同じメッセージが二回表示されます。
2019-04-04 09:37:06.219 : get_time 2019-04-04 09:37:08.247 : HELLO!!! 2019-04-04 09:37:08.247 : HELLO!!! 2019-04-04 09:37:08.247 : 待機状態です、、、 2019-04-04 09:37:08.247 : 待機状態です、、、 2019-04-04 09:37:11.258 : 待機状態です、、、 2019-04-04 09:37:11.258 : 待機状態です、、、 2019-04-04 09:37:14.268 : 待機状態です、、、 2019-04-04 09:37:14.268 : 待機状態です、、、 2019-04-04 09:37:17.279 : 待機状態です、、、 2019-04-04 09:37:17.279 : 待機状態です、、、 2019-04-04 09:37:20.290 : print_hello_exit 2019-04-04 09:37:20.290 : print_hello_exit 2019-04-04 09:37:21.304 : get_time 2019-04-04 09:37:21.304 : get_time 2019-04-04 09:37:24.346 : get_time 2019-04-04 09:37:25.360 : HELLO!!! 2019-04-04 09:37:25.360 : 待機状態です、、、 2019-04-04 09:37:25.360 : HELLO!!! 2019-04-04 09:37:25.360 : 待機状態です、、、
該当のソースコード
Python
1import schedule 2import time 3import concurrent.futures 4 5from datetime import datetime, timedelta 6 7 8# ******************************** 9# 関数 10# ******************************** 11 12 13def multi_thread(): 14 executor = concurrent.futures.ThreadPoolExecutor(max_workers=5) 15 executor.submit(suchedule_event_communicate) 16 executor.submit(suchedule_event_run_print_hello) 17 18 19def get_timestring(): 20 """ 21 ミリ秒までを保持できる現在時刻を取得 22 :return: 23 """ 24 now = datetime.now() 25 return now.strftime('%Y-%m-%d %H:%M:%S.%f')[:-3] 26 27 28def print_message(run_time=get_timestring(), message=""): 29 print(run_time + " : " + message) 30 31 32def suchedule_event_communicate(): 33 """ 34 3秒に一回時刻を表示する 35 :return: 36 """ 37 schedule.every(3/60).minutes.do(print_time) 38 while True: 39 schedule.run_pending() 40 time.sleep(1) 41 42 43def print_time(): 44 print_message(get_timestring(), "get_time") 45 46 47def suchedule_event_run_print_hello(): 48 """ 49 5秒に一回HELLO!!!を表示する 50 :return: 51 """ 52 schedule.every(5/60).minutes.do(print_hello) 53 while True: 54 schedule.run_pending() 55 time.sleep(1) 56 57 58def print_hello(): 59 now_time = get_timestring() 60 print_message(now_time, "HELLO!!!") 61 62 # HELLO!!!が表示されてから10秒間は待機時間 63 while str(datetime.strptime(now_time, '%Y-%m-%d %H:%M:%S.%f') + timedelta( 64 seconds=10)) > get_timestring(): 65 print_message(get_timestring(), "待機状態です、、、") 66 time.sleep(3) 67 68 print_message(get_timestring(), "print_hello_exit") 69 70 71# ******************************** 72# main 73# ******************************** 74 75 76# 定期処理起動 77multi_thread() 78 79
試したこと
マルチスレッドでwhileを使用する以下の処理であれば交互にメッセージを出力(同じ時刻・メッセージなし)しました。
scheduleの中で、whileや待機(sleep)と組み合わせるのが良くないのでしょうか。
Python
1import time 2import concurrent.futures 3from datetime import datetime 4 5 6def get_timestring(): 7 """ 8 ミリ秒までを保持できる現在時刻を取得 9 :return: 10 """ 11 now = datetime.now() 12 return now.strftime('%Y-%m-%d %H:%M:%S.%f')[:-3] 13 14 15def print_message(run_time=get_timestring(), message=""): 16 print(run_time + " : " + message) 17 18 19def func1(): 20 while True: 21 print_message(get_timestring(), "func1") 22 time.sleep(1) 23 24 25def func2(): 26 while True: 27 print_message(get_timestring(), "func2") 28 time.sleep(1) 29 30 31if __name__ == "__main__": 32 executor = concurrent.futures.ThreadPoolExecutor(max_workers=2) 33 executor.submit(func1) 34 executor.submit(func2) 35
試したこと②
suchedule_event_run_print_hello内に記載されていたwhileをなくしました。
そうするとうまくいくようです。
Python
1import schedule 2import time 3import concurrent.futures 4 5from datetime import datetime, timedelta 6 7 8# ******************************** 9# 関数 10# ******************************** 11 12 13def multi_thread(): 14 executor = concurrent.futures.ThreadPoolExecutor(max_workers=5) 15 executor.submit(suchedule_event_communicate) 16 executor.submit(suchedule_event_run_print_hello) 17 18 19def get_timestring(): 20 """ 21 ミリ秒までを保持できる現在時刻を取得 22 :return: 23 """ 24 now = datetime.now() 25 return now.strftime('%Y-%m-%d %H:%M:%S.%f')[:-3] 26 27 28def print_message(run_time=get_timestring(), message=""): 29 print(run_time + " : " + message) 30 31 32def suchedule_event_communicate(): 33 """ 34 3秒に一回時刻を表示する 35 :return: 36 """ 37 schedule.every(3/60).minutes.do(print_time) 38 while True: 39 schedule.run_pending() 40 time.sleep(1) 41 42 43def print_time(): 44 print_message(get_timestring(), "get_time") 45 46 47def suchedule_event_run_print_hello(): 48 """ 49 5秒に一回HELLO!!!を表示する 50 :return: 51 """ 52 schedule.every(5/60).minutes.do(print_hello) 53 # whileをなくしました。 54 schedule.run_pending() 55 time.sleep(1) 56 57 58def print_hello(): 59 now_time = get_timestring() 60 print_message(now_time, "HELLO!!!") 61 62 # HELLO!!!が表示されてから10秒間は待機時間 63 while str(datetime.strptime(now_time, '%Y-%m-%d %H:%M:%S.%f') + timedelta( 64 seconds=10)) > get_timestring(): 65 print_message(get_timestring(), "待機状態です、、、") 66 time.sleep(3) 67 68 print_message(get_timestring(), "print_hello_exit") 69 70 71# ******************************** 72# main 73# ******************************** 74 75 76# 定期処理起動 77multi_thread() 78 79
2019-04-05 10:00:37.653 : get_time 2019-04-05 10:00:39.653 : HELLO!!! 2019-04-05 10:00:39.661 : 待機状態です、、、 2019-04-05 10:00:42.661 : 待機状態です、、、 2019-04-05 10:00:45.661 : 待機状態です、、、 2019-04-05 10:00:48.662 : 待機状態です、、、 2019-04-05 10:00:51.662 : print_hello_exit 2019-04-05 10:00:52.662 : get_time 2019-04-05 10:00:55.662 : get_time 2019-04-05 10:00:56.662 : HELLO!!! 2019-04-05 10:00:56.663 : 待機状態です、、、 2019-04-05 10:00:59.663 : 待機状態です、、、
補足情報(FW/ツールのバージョンなど)
Python 3.7.0(pycharm使用)
windows7 64bit
回答2件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2019/04/05 07:56
2019/04/09 00:33