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

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

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

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

Python

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

Q&A

解決済

3回答

5956閲覧

マルチスレッド化における優先度について

退会済みユーザー

退会済みユーザー

総合スコア0

Raspberry Pi

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

Python

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

0グッド

0クリップ

投稿2018/11/15 06:06

下記のプログラムを実行した際に、"GPS情報"と"「ok」の表示"を並列処理させたかったのですが、「ok」がGPSとほぼ同時に表示されてしまい並列動作していることが確認できませんでした。

本来は、1秒毎にGPS表示しながら同時進行で2秒毎にokを表示させたかったのですがうまく動作しませんでした。

どこか不備が有ればおしえていただきたいです。
よろしくお願いします。。

python

1 2import time, datetime, threading, serial, micropyGPS 3 4gps = micropyGPS.MicropyGPS(9, 'dd') 5 6#関数------------------------------------------------------ 7def rungps(): 8 s = serial.Serial('/dev/serial0', 9600, timeout=10) 9 s.readline() 10 while True: 11 sentence = s.readline().decode('utf-8') 12 if sentence[0] != '$': 13 continue 14 for x in sentence: 15 gps.update(x) 16 17 if gps.clean_sentences > 20: 18 print('緯度経度: %2.8f, %2.8f' % (gps.latitude[0], gps.longitu$ 19 other() 20 time.sleep(1.0) 21#---------------------------------------------------------- 22 23def other(): 24 print('ok') 25 time.sleep(2.0) 26#---------------------------------------------------------- 27if __name__ == "__main__": 28 gpsthread = threading.Thread(target=rungps, args=()) 29 otherthread = threading.Thread(target=other) 30#gpsthread.daemon = True 31 gpsthread.start() 32 otherthread.start() 33

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

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

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

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

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

guest

回答3

0

ベストアンサー

質問に書かれたプログラムは、以下のように動作しているはずです。

  1. rungpsを実行するgpsthreadスレッドが、mainの中の"gpsthread.start()"で起動される。

 gpsthreadは、シリアル通信からデータを読みだし(シリアル通信に残っているごみデータの読み飛ばし(?))、以下の動作を行う無限ループを実行する
1-1) シリアル通信からデータを読み出し、それでgpsの更新(?)を行う
1-2) rungpsの中の "print('緯度経度: %2.8f, %2.8f' % (gps.latitude[0], gps.longitu$"で緯度、経度が表示される。
1-3) rungpsの中の次の行 "other()"でother関数が呼び出され、'ok'の表示と、2秒間の待ち(sleep(2.0))が行われる。(緯度経度の表示をするコードと'ok'を表示するコードは連続しているので、当然ながら「ok」がGPSとほぼ同時に表示されることになります。
1-4) rungpsの中の次の行 "sleep(1.0)"で1秒間の待ちが行われた後に、ループの最初に戻って、1-1からの動作を繰り返す

  1. other()を実行するotherthreadスレッドが、mainの中の次の行"otherthread.start()"で起動される。

2-1) other()関数は、'ok'の表示と、2秒間の待ち(sleep(2.0))を行うだけなので、otherthreadスレッドは起動から2秒後には(実行が終わったので)消滅する。

===
「本来は、1秒毎にGPS表示しながら、同時進行で2秒毎にokを表示させたかったのですがうまく動作しませんでした」の理由

A) [1秒毎にGPS表示しながら]
rungpsのループの中に、シリアル通信からの読み出し("sentence = s.readline().decode('utf-8')")をするコードが含まれています。
シリアル通信にどのようなデータが送られていることになっているのかわかりませんが、シリアル通信からデータが来なければループはデータ待ちで止まることになります。1秒の時間待ち以外に、シリアル通信待ちが入る(データが来るのを待つ時間、届いたデータを読み出す時間が発生する)ので、不定期にループが実行されているのではと思われます。
ループの前にシリアル通信から一連の指示データを読み込むようにして、ループ内では指示データに従って動作する(シリアル通信は使わない)ようにすれば、1秒ごとに動作するように出来ると思われます。(2秒の待ちを含む other()の呼び出しをやめてください。そうすれば3秒+α間隔で回っていたループが、1秒+アルファ間隔で回るようになるはず)
また、"if sentence[0] != '$':"の付近は、シリアル通信から'$'が送られてきたら、何かの動作をさせるコードの断片(残骸)だと思われますが、今はcontinueで何もなかったことにしてしまっているので改良が必要だと思います。 

B) [2秒毎にokを表示]
他の方も指摘しているように、other関数はループを含まないので、一度'ok'を表示したら終わりです。(other関数を実行するotherthreadスレッドも、実行が終わったら消滅します)
以下のように修正すれば、otherthreadスレッドが無限ループで2秒毎にokを表示するようになります。

def other(): While True: print('ok') time.sleep(2.0)

投稿2018/11/16 05:40

編集2018/11/16 05:47
coco_bauer

総合スコア6915

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

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

退会済みユーザー

退会済みユーザー

2018/11/20 09:04

................................................................................. ご回答ありがとうございます。 ご指摘受けまして以下のように変更致しました。 ですが、今度は「ok」ばかり出て「緯度経度」は一度しか出ませんでした。 そのターミナルの様子も載せますのでご確認下さい。 .................................................................................. 以下変更後の全文 .................................................................................. import time, datetime, threading, serial, micropyGPS gps = micropyGPS.MicropyGPS(9, 'dd') #関数------------------------------------------------------ def rungps(): s = serial.Serial('/dev/serial0', 9600, timeout=10) s.readline() while True: sentence = s.readline().decode('utf-8') if sentence[0] != '$': continue for x in sentence: gps.update(x) #---------------------------------------------------------- def other(): while True: print('ok') time.sleep(2.0) #---------------------------------------------------------- gpsthread = threading.Thread(target=rungps, args=()) otherthread = threading.Thread(target=other) gpsthread.daemon = True gpsthread.start() otherthread.start() while True: if gps.clean_sentences > 20: print('緯度経度: %2.8f, %2.8f' % (gps.latitude[0], gps.longitude[0])) other() time.sleep(1.0) .................................................................................. .................................................................................. .................................................................................. 以下実行結果 .................................................................................. pi@raspberrypi:~/Desktop $ python3 09.py ok ok ok 緯度経度: 0.00000000, 0.00000000 ok ok ok ok ok ok ok ok ok ok ok ok ok ok ok ok ok ok ok ok ok ok ok ok ok ok ok ok
coco_bauer

2018/11/21 00:24

緯度経度の表示が1度しか起こらないのは、if文の条件 "gps.clean_sentences > 20"が成立するのが1度しか起こっていないからだと思います。表示される緯度経度が(0.0,0.0)であることを考え合わせると、GPSモジュールの制御がうまくいっていないのではないかと思われます。 まず、GPSモジュールに指示を送って、緯度経度を表示するプログラムで動作確認をしてみてはいかがでしょうか。
guest

0

other() はループされてないので、1回しか実行されませんよ。

投稿2018/11/15 17:33

CodeLab

総合スコア1939

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

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

退会済みユーザー

退会済みユーザー

2018/11/16 03:36

いえ。もう一度実行してみたのですが繰り返し表示されます
guest

0

落ち着いて考えれば分かると思います。

otherスレッドは最初に一度start()で起動されて終わりで、その後は、GPSスレッドのなかで緯度経度表示の後で呼び出されるだけです。

#コメントを受けて追記

当方、これが初めてのPythonでして

おそらく、プログラミングが初めてですよね?
otherrungps同様に無限ループにする
rungpsからotherを呼び出すのをやめる
の2箇所を修正します。

Python

1import time, datetime, threading, serial, micropyGPS 2 3gps = micropyGPS.MicropyGPS(9, 'dd') 4 5#関数------------------------------------------------------ 6def rungps(): 7 s = serial.Serial('/dev/serial0', 9600, timeout=10) 8 s.readline() 9 while True: 10 sentence = s.readline().decode('utf-8') 11 if sentence[0] != '$': 12 continue 13 for x in sentence: 14 gps.update(x) 15 16 if gps.clean_sentences > 20: 17 print('緯度経度: %2.8f, %2.8f' % (gps.latitude[0], gps.longitu$ 18 time.sleep(1.0) 19#---------------------------------------------------------- 20 21def other(): 22 while True: 23 print('ok') 24 time.sleep(2.0) 25#---------------------------------------------------------- 26if __name__ == "__main__": 27 gpsthread = threading.Thread(target=rungps, args=()) 28 otherthread = threading.Thread(target=other) 29#gpsthread.daemon = True 30 gpsthread.start() 31 otherthread.start()

投稿2018/11/15 06:28

編集2018/11/16 06:20
otn

総合スコア84505

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

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

退会済みユーザー

退会済みユーザー

2018/11/15 17:19

申し訳ありませんが、当方、これが初めてのPythonでしておっしゃっている意味がよく理解できません。 どこをどのように直すとこの症状は改善されるのでしょうか?
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問