【Python】TkinterとPyserialとMulti Thread 。。 いい具合にやってくれる?【GUI+並列】

スポンサーリンク
広告

ちょっとだけGUIを書こうと。。

【Python】GUI用のTkinterのメモTips集 pygubuかも【リンク集】
PythonでちょっとGUI作りたい ArduinoやESP32とPCの通信とか、Raspberry Piなどで、ちょっとした画面入出力G...

COMポートを読んで来て、表示させるだけなんですが。。 表示とCOM取得を同時に並列で動かさないと。。コマンドラインにprintするだけなら。。だーっと表示できるものが、GUIだと。。それぞれマルチスレッドで動かさないとだめなんですね(笑)当たり前だけど。。

import threading

って入っているコードがあって。。やっと気づいた(笑)

でも。。

import concurrent.futures

というのもあって。。どっちなのかな?と。。

Threading

threading --- スレッドベースの並列処理 — Python 3.10.4 ドキュメント

こちらは、Threadingを使う方法。。stackoverflowで見つけた回答を動くように改変。コムポートなどの設定と、ser.writeやreadでUTF-8 を asciiと変えてます。

Button problem in multi-threading Python Tkinter Serial Monitor
I try to create a Serial Monitor which can send and receive messages from a Serial Port with Tkinter as GUI. I did two threads for not having a freezed GUI when...

コード自体 赤字のところが threadingに関係するところ

import threading
from tkinter import *
import tkinter as tk
import serial
root = tk.Tk()
COM = "COM4"
ser = serial.Serial(port=COM, baudrate=57600, bytesize=serial.EIGHTBITS, parity=serial.PARITY_NONE, timeout=2)
ser.isOpen()
msg = ""


# read Serial
def ReadSerial():
 global msg
 msg = ""
 msg = ser.readline()[:-2].decode("ascii")
 if msg != "":
 print(msg)

return msg
# write Serial
def WriteSerial(sendmsg):
 print("send")
 ser.write(bytes(sendmsg, 'ascii'))
 ReadSerial()


# Tkinter
root.title("WIP NAME")
root.geometry("650x400")
inputData = Entry(root, text="<Slave1&p>") # input for enter the message to write
entrymsg = inputData.get() # get the massage
buttonMsg = Button(root, text="send", command = lambda: WriteSerial(inputData.get())) # create a send button for send the message
readData = Label(root, text=msg) # show message in Tkinter
ReadSerial()
# show items
inputData.grid()
readData.grid()
buttonMsg.grid()


# GUI thread
def TkinterGui():
 while 1==1:
 global msg
 entrymsg = inputData.get()


# Serial thread
def SerialProgram():
  global msg
 while 1==1:
 ReadSerial()
 readData["text"]=msg
 readData.update_idletasks()


x = threading.Thread(target=TkinterGui, args=())
y = threading.Thread(target=SerialProgram, args=())
x.start()
y.start()

root.mainloop()

どうやら・・ 関数を定義して、TkinterGuiの関数と、SerialProgramを、スレッドですよって宣言して、それらをスタートさせると、それぞれが同時に動くって感じですね。

Tkinter に作った Labelに受信した値を表示させるってことなんですが、こういう風にしないとTkinter(画面)に反映されないんですよね。。

わかりやすい。

他の例も。。

Pythonのサンプルコード | テスビット

Concurrent.futures

どうも。。これは、非同期実行ができるようです。順番にするというより、同時に動いている感じですかね?表現方法違いかも? よくわかってないけど。。 受信と送信を別プロセスで動かす感じです。

concurrent.futures -- 並列タスク実行 — Python 3.10.4 ドキュメント

コードの例は、こちらから。。

import serial
import time
import concurrent.futures

ser = serial.Serial('COM4',57600,timeout=None) 

def func1():
 while True:
 line = ser.readline()
 print(line)

def func2():
 while True:
  flag=bytes(input(),'utf-8')
  ser.write(flag)
  if(flag==bytes('a','utf-8')):
    break;
  time.sleep(1)

 ser.close()

if __name__ == "__main__":
executor = concurrent.futures.ThreadPoolExecutor(max_workers=2)
executor.submit(func1)
executor.submit(func2)

こちらも使い方は同じような感じですね。

Afterを使ってるのもある。

こんなのもありますね。

インターバルを自分自身で用意して、1秒に一回づつしか通信しないようにしてます。

なるほど。。って。。この場合、Tkinter部分のループと同時に動いているってことかな?

テクシオ・テクノロジーによる実用的Pythonのプログラミング

並行処理と並列処理

ここに綺麗にまとまっているのがありました。

Pythonの並行処理を理解したい [マルチスレッド編]
【Python】concurrent.futures の使い方【並列処理】
concurrent.futuresコンカレント ドット フューチャース で並列処理する Python コード例を書きました。ThreadPoolExecutorスレッド プール エクセキューター() のスレッドプールを使った方法と、Pro

thread(時分割) と Process(CPU並列) を同じような感じで使えるようにしたのが、concurrent.futures って感じですかね。

TkinterとSerialを同時に使うって、めんどくさいな(笑) どっちもループで動いているので処理の受け渡しが必要ってことですね。

昔のVB6.0とかでやってた時ってこんな処理してたっけ??(笑) ってやってたような気がする(笑) 通信しだすと、ボタン受け付けな~いって。。そういえば。。って思い出した(笑)

コメントを残していただけるとありがたいです

Loading Facebook Comments ...
%d人のブロガーが「いいね」をつけました。