python3 GUI用户界面总结(以串口调试为例,持续改进)
本文主要目的是總結(jié)串口調(diào)試助手開發(fā)過程中遇到的問題和解決方法,以及總結(jié)通用資料以備后續(xù)參考,歡迎批評指正。
需要掌握的基礎(chǔ)內(nèi)容:
- 涉及到的python庫的基本操作
- 串口通信基礎(chǔ)
- 進(jìn)制轉(zhuǎn)換等算法問題
- python3基礎(chǔ)語言和方法
本文安排:
- python庫簡介,包括tkiner、serial
- 開發(fā)上位機(jī)過程中遇到的函數(shù)調(diào)用方式、庫方法使用方式
- 涉及具體算法需要掌握的知識基礎(chǔ)
- 其他可能用到的資料
內(nèi)容比較瑣碎,可根據(jù)目錄查看所需內(nèi)容。詳情查看所附鏈接。
文章目錄
- 開發(fā)上位機(jī)用到的python庫
- serial簡介
- PyQt5簡介
- tkinter簡介
- tkinter包含的控件
- mainloop的實(shí)質(zhì)
- tkinter text
- Scrollbar控件-添加滑動條
- numpy
- threading庫簡介
- join
- 開發(fā)串口調(diào)試助手
- 串口類
- 打包GUI程序?yàn)閑xe文件
- 錯(cuò)誤解決
- 讀取串口數(shù)據(jù)時(shí)崩潰、無數(shù)據(jù)、數(shù)據(jù)不全
- 丟包
- 串口通信之?dāng)?shù)據(jù)丟失
- python相關(guān)
- 為什么要加if __name __==‘__main __’:
- 線程
- 并發(fā)與并行
- 線程與進(jìn)程
- 單線程與多線程
- 常見異常類型
- 重命名變量方法
- 運(yùn)算
- 原碼補(bǔ)碼轉(zhuǎn)換
- python指數(shù)**
- 數(shù)值與字符串
- python讀取字符串長度len()
- python的數(shù)值與字符串區(qū)分
- python二進(jìn)制-十進(jìn)制轉(zhuǎn)換
- python字符串轉(zhuǎn)十進(jìn)制整型
- python截取字符串
- python 替換字符串
- 列表插入元素append
- python 二維列表
- python二維列表對應(yīng)元素相加
- encode與decode
- 文件
- 讀寫文件(txt、csv、excel)
- 文件操作模式
- python跨文件調(diào)用函數(shù)
- datetime庫 獲取當(dāng)前時(shí)間
- 實(shí)例鏈接
- 計(jì)算器GUI實(shí)例
- 串口調(diào)試助手GUI實(shí)例
- 讀取串口數(shù)據(jù)并寫入txt文件
開發(fā)上位機(jī)用到的python庫
此處僅為庫的簡介,以及實(shí)際開發(fā)上位機(jī)過程中遇到的重要的控件。
serial簡介
serial 是串口接口庫,與串口通信相關(guān)的操作都需使用。
程序中import serial 實(shí)際安裝的是pyserial庫,關(guān)于pyserial的詳細(xì)手冊鏈接和資料,可參見: python庫之pyserial用法_CSDN博客
import serial后,工程文件夾下會有serial文件夾。
serial文件夾中的serialwin32.py可以找到庫函數(shù)的定義,如果看了上面鏈接中的函數(shù)說明仍然有疑惑,可以自行查看函數(shù)定義。
這個(gè)文件里有from serial import win32
涉及到win32的,可以到Microsoft文檔中找資料,如下圖為COMSTST結(jié)構(gòu)體的說明。
PyQt5簡介
Python上位機(jī)軟件圖形界面實(shí)戰(zhàn)(2)_Funny-CSDN博客_python適合開發(fā)上位機(jī)嗎
PyQt5是用于圖形化界面設(shè)計(jì)的,僅設(shè)計(jì)界面,功能函數(shù)還需自己編寫。對界面要求不高的上位機(jī)只需用tkinter庫即可完成界面和功能的設(shè)計(jì)。
上位機(jī)圖形界面開發(fā)設(shè)計(jì)用QT Designer就可以了。但是qt designer生成的是.ui文件,我們需要將.ui轉(zhuǎn)換為我們用的py文件。
以下僅以tkinter和serial作為開發(fā)調(diào)試串口助手GUI的核心庫,此外可能會用到time庫進(jìn)行延時(shí)操作。
tkinter簡介
Graphical User Interfaces with Tk — Python 3.8.5 documentation
Python GUI 編程(Tkinter) | 菜鳥教程
tkinter庫是Tcl / Tk的Python接口,用于制作和處理圖形用戶界面(Graphical User Interface,簡稱 GUI,又稱圖形用戶接口)。
Tk / Tcl提供了與平臺無關(guān)的窗口工具箱,使用tkinter軟件包及其擴(kuò)展名tkinter.tix和tkinter.ttk模塊的Python程序員可以使用該工具箱。
tkinter包是Tcl / Tk之上的面向?qū)ο髮印R褂胻kinter,您無需編寫Tcl代碼,但您需要查閱Tk文檔,有時(shí)還需要查閱Tcl文檔。 tkinter是一組將Tk小部件實(shí)現(xiàn)為Python類的包裝器。另外,內(nèi)部模塊_tkinter提供了線程安全機(jī)制,該機(jī)制允許Python和Tcl進(jìn)行交互。
tkinter的主要優(yōu)點(diǎn)是速度快,并且通常與Python捆綁在一起。盡管其標(biāo)準(zhǔn)文檔weak,但仍然可以找到不錯(cuò)的材料,其中包括:參考資料,教程,書籍等。但是,您可能會對許多其他GUI庫感興趣,有關(guān)替代方法的更多信息,請參見“其他圖形用戶界面包”。
注意,不同版本的python調(diào)用庫的名稱不同。
#!/usr/bin/python3import tkinter # 創(chuàng)建Tk top = tkinter.Tk() # 進(jìn)入消息循環(huán) top.mainloop() #!/usr/bin/python2 # -*- coding: UTF-8 -*-import Tkinter # 創(chuàng)建Tk top = Tkinter.Tk() # 進(jìn)入消息循環(huán) top.mainloop()tkinter包含的控件
Python GUI之tkinter窗口視窗教程大集合 - 洪衛(wèi) - 博客園
控件介紹和基本操作見鏈接。
Tkinter支持16個(gè)核心的窗口部件,這個(gè)16個(gè)核心窗口部件類簡要描述如下:
| Button | 一個(gè)簡單的按鈕,用來執(zhí)行一個(gè)命令或別的操作。 |
| Canvas | 組織圖形。這個(gè)部件可以用來繪制圖表和圖,創(chuàng)建圖形編輯器,實(shí)現(xiàn)定制窗口部件。 |
| Checkbutton | 代表一個(gè)變量,它有兩個(gè)不同的值。點(diǎn)擊這個(gè)按鈕將會在這兩個(gè)值間切換。 |
| Entry | 文本輸入域。 |
| Frame | 一個(gè)容器窗口部件。幀可以有邊框和背景,當(dāng)創(chuàng)建一個(gè)應(yīng)用程序或dialog(對話)版面時(shí),幀被用來組織其它的窗口部件。 |
| Label | 顯示一個(gè)文本或圖象。 |
| Listbox | 顯示供選方案的一個(gè)列表。listbox能夠被配置來得到radiobutton或checklist的行為。 |
| Menu | 菜單條。用來實(shí)現(xiàn)下拉和彈出式菜單。 |
| Menubutton | 菜單按鈕。用來實(shí)現(xiàn)下拉式菜單。 |
| Message | 顯示一文本。類似label窗口部件,但是能夠自動地調(diào)整文本到給定的寬度或比率。 |
| Radiobutton | 代表一個(gè)變量,它可以有多個(gè)值中的一個(gè)。點(diǎn)擊它將為這個(gè)變量設(shè)置值,并且清除與這同一變量相關(guān)的其它radiobutton。 |
| Scale | 允許你通過滑塊來設(shè)置一數(shù)字值。 |
| Scrollbar | 為配合使用canvas, entry, listbox, and text窗口部件的標(biāo)準(zhǔn)滾動條。 |
| Text | 格式化文本顯示。允許你用不同的樣式和屬性來顯示和編輯文本。同時(shí)支持內(nèi)嵌圖象和窗口。 |
| Toplevel | 一個(gè)容器窗口部件,作為一個(gè)單獨(dú)的、最上面的窗口顯示。 |
| messageBox | 消息框,用于顯示你應(yīng)用程序的消息框。(Python2中為tkMessagebox) |
注意在Tkinter中窗口部件類沒有分級;所有的窗口部件類在樹中都是兄弟關(guān)系。
所有這些窗口部件提供了Misc和幾何管理方法、配置管理方法和部件自己定義的另外的方法。此外,Toplevel類也提供窗口管理接口。這意味一個(gè)典型的窗口部件類提供了大約150種方法。
mainloop的實(shí)質(zhì)
mainloop()是tkinker的界面初始化完成后,開啟界面及其調(diào)度管理功能的函數(shù)。用戶只需按照庫中已有的方法編寫好所需的功能和界面,再執(zhí)行mainloop,就可以實(shí)現(xiàn)上位機(jī)的程序開發(fā)過程。
以下偽代碼說明了其實(shí)質(zhì):鏈接
def mainloop():while the main window has not been closed:if an event has occurred:run the associated event handler function只要GUI還在屏幕上,mainloop調(diào)用就不會返回執(zhí)行代碼。
tkinter text
text:Python - Tkinter Text - Tutorialspoint
上面的鏈接中介紹了tkinter庫中的關(guān)于文本text的屬性、方法等。需要GUI顯示多行文字時(shí)使用,常見的應(yīng)用是顯示輸出數(shù)據(jù)、顯示輸入文字等。下面是關(guān)于方法的截圖,insert用于在文本中添加內(nèi)容,see用于選擇GUI上顯示的位置。
text在GUI上長這樣:
Scrollbar控件-添加滑動條
Tkinter 組件詳解(九):Scrollbar_一只沒有腳的豬的博客-CSDN博客
Scrollbar 組件通常與 Text 組件、Canvas 組件和 Listbox 組件一起使用,水平滾動條還能跟 Entry 組件配合。
text控件默認(rèn)沒有滑動條,所以當(dāng)文本內(nèi)容超出窗口大小時(shí)不能判斷內(nèi)容的多少和位置,很不方便。下面是scrollbar和text一起使用的例子。
如果只有一個(gè)滑動條,還可以綁定鼠標(biāo)滾輪和滑動條(綁定后鼠標(biāo)即使不點(diǎn)擊選中窗口,滑動滾輪也可以翻頁)
# 給text添加滑動條:# 設(shè)置滑動條,設(shè)置其位置st = tkinter.Scrollbar(self.mainwin) # 在text旁邊加# st.pack(side=tkinter.RIGHT, fill=tkinter.Y) # 在整個(gè)窗口旁邊加滑動條# textself.SendDataView = ScrolledText(self.mainwin, width=60, height=3,font=("宋體", 10)) # text實(shí)際上是一個(gè)文本編輯器self.SendDataView.place(x=230, y=35) # 顯示# 在text右邊添加滑動條self.SendDataView.focus_set() # 不知何用?st.config(command=self.SendDataView.yview)# 綁定鼠標(biāo)滾輪和滑動條# self.mainwin.bind("<MouseWheel>", self._on_mousewheel)鏈接
numpy
Python、Numpy 教程 | NumPy 中文
threading庫簡介
手冊(全英文):threading — Thread-based parallelism — Python 3.8.5 documentation
threading:Python 3 之后的線程模塊,提供了功能豐富的多線程支持,推薦使用。
Python 主要通過兩種方式來創(chuàng)建線程:(鏈接)
- 使用 threading 模塊中 Thread 類的構(gòu)造器創(chuàng)建線程。即直接對類 threading.Thread 進(jìn)行實(shí)例化創(chuàng)建線程,并調(diào)用實(shí)例化對象的 start() 方法啟動線程。
- 繼承 threading 模塊中的 Thread 類創(chuàng)建線程類。即用 threading.Thread 派生出一個(gè)新的子類,將新建類實(shí)例化創(chuàng)建線程,并調(diào)用其 start() 方法啟動線程。
線程需要手動啟動才能運(yùn)行,threading 模塊提供了 start() 方法用來啟動線程。
import threadingdef t_receive():# 接收...def t_save():# 保存...# 創(chuàng)建線程 t1 = threading.Thread(target=t_receive) t2 = threading.Thread(target=t_save)# 設(shè)置t2為守護(hù)線程,即服務(wù)程序 t2.setDaemon(True)# 開啟線程 t1.start() t2.start()# 線程占用CPU直至死亡 t1.join() t2.join()代碼鏈接
join
join() 方法的功能是在程序指定位置,優(yōu)先讓該方法的調(diào)用者使用 CPU 資源。該方法的語法格式如下:
thread1.join( [timeout] )
其中,thread1 為 thread 類或其子類的實(shí)例化對象;timeout 參數(shù)作為可選參數(shù),其功能是指定 thread 線程最多可以霸占 CPU 資源的時(shí)間(以秒為單位),如果省略,則默認(rèn)直到 thread 執(zhí)行結(jié)束(進(jìn)入死亡狀態(tài))才釋放 CPU 資源。
開發(fā)串口調(diào)試助手
背景知識(新手入門):
關(guān)于串口上位機(jī)編程你需掌握的背景知識_Robert Zhang-CSDN博客
哈嘍,上位機(jī)(上位機(jī)開發(fā)指南)_Robert Zhang_robert_cysy-CSDN博客
基本過程:
- 完成所需功能(選擇串口、選擇波特率、發(fā)送、接收、顯示、輸出結(jié)果到文件)
- 設(shè)計(jì)界面(文本、按鈕、選項(xiàng)框、大小、位置、顏色)
- 連接功能函數(shù)和界面
- 測試,解決bug
- 封裝,打包為exe文件等等
代碼重點(diǎn)參考:
python實(shí)現(xiàn)串口通訊小程序(GUI界面)_明志的博客-CSDN博客_pycharm 開發(fā)串口
上位機(jī)開發(fā)工具對比:
原來這才是大家常用的上位機(jī)開發(fā)平臺_Robert Zhang-CSDN博客
下面只總結(jié)一些具體的方法和代碼。
串口類
定義串口處理類,后續(xù)操作可直接調(diào)用。
import serial import serial.tools.list_ports# 串口處理類 class SerialAchieve:def __init__(self, band=3000000, check="無校驗(yàn)位", data=8, stop=1):self.port = None# 獲取可用串口self.port_list = list(serial.tools.list_ports.comports())assert (len(self.port_list) != 0), "無可用串口"self.bandRate = bandself.checkbit = checkself.databit = dataself.stopbit = stop# 讀寫的數(shù)據(jù)self.read_data = Noneself.write_data = Nonepassdef show_port(self):for i in range(0, len(self.port_list)):print(self.port_list[i])def show_other(self):print("波特率:" + self.bandRate)print("校驗(yàn)位:" + self.checkbit)print("數(shù)據(jù)位:" + self.databit)print("停止位:" + self.stopbit)# 返回串口def get_port(self):return self.port_list# 打開串口def open_port(self, port):self.port = serial.Serial(port, self.bandRate, timeout=1) # timeout=None# 關(guān)閉串口def delete_port(self):if self.port != None:self.port.close()print("關(guān)閉串口完成")else:passdef Read_data(self): # self.port.read(self.port.in_waiting) 表示全部接收串口中的數(shù)據(jù)self.read_data = self.port.read(self.port.in_waiting) # 讀取數(shù)據(jù)return self.read_data.decode("utf-8")def Write_data(self, data):if self.port.isOpen() == False:print("串口打開錯(cuò)誤")else:self.port.write(data.encode("utf-8")) # 返回的是寫入的字節(jié)數(shù)# 主類 class MainSerial:def __init__(self):# 定義串口變量self.port = Noneself.band = Noneself.check = Noneself.data = Noneself.stop = Noneself.myserial = None# 創(chuàng)建串口對象self.myserial = SerialAchieve(int(self.band), self.check, self.data, self.stop)# 處理串口值self.port_list = self.myserial.get_port()port_str_list = [] # 用來存儲切割好的串口號for i in range(len(self.port_list)):# 將串口號切割出來lines = str(self.port_list[i])str_list = lines.split(" ")port_str_list.append(str_list[0])# 主函數(shù) if __name__ == '__main__':my_ser1 = MainSerial()my_ser1.show()打包GUI程序?yàn)閑xe文件
如果要脫離python環(huán)境使用,則需要將寫好gui的python3的py文件打包成exe程序。
鏈接:
步驟(詳細(xì)步驟見鏈接):
例:需要打包程序目錄為:D:\automation\autotest_tool\interface_param_change_tool
切換指令:cd D:\automation\autotest_tool\interface_param_change_tool
例:需要打包的python程序?yàn)?#xff1a;runner.py
指令:pyinstaller -F runner.py
打包成功后項(xiàng)目中新增dist文件,進(jìn)入dist文件,點(diǎn)擊運(yùn)行打包好的exe程序
錯(cuò)誤解決
讀取串口數(shù)據(jù)時(shí)崩潰、無數(shù)據(jù)、數(shù)據(jù)不全
python-在Python3.7的環(huán)境下,每次都是執(zhí)行到serial.read()就卡住了。——CSDN問答頻道
上位機(jī)崩潰(不斷輸出,鼠標(biāo)點(diǎn)擊后無響應(yīng))。
可能是由于陷入死循環(huán)中,阻塞了,不能進(jìn)行其他操作。可檢查讀取串口的函數(shù),看看是不是無限循環(huán),無法退出。還可能是要讀取的數(shù)據(jù)太多了,超出緩存區(qū)大小。
解決:增加退出條件,或建立線程(需要操作系統(tǒng)相關(guān)知識)。
關(guān)于超出緩存的問題,可參考下面鏈接關(guān)于緩存區(qū)大小和解決思路的討論:
串口一次最大能接收多少字節(jié)-CSDN論壇
上位機(jī)要接收兩次才能將下位機(jī)發(fā)送數(shù)據(jù)顯示完全。
- 緩沖區(qū)決定一次接收數(shù)據(jù)大小。
- 一般串口硬件只有1個(gè)字節(jié)緩沖,其他都是系統(tǒng)自己的內(nèi)存做暫存緩沖的,而且一般不會很大。最好自己設(shè)置一個(gè)內(nèi)存,多少取決于你的內(nèi)存大小,中斷消息處理串口數(shù)據(jù),存到自己的緩沖區(qū),等到字節(jié)到了你需要的,再從緩沖區(qū)讀出。這樣就非常靈活了。鏈接
接收數(shù)據(jù),但無數(shù)據(jù)顯示。
首先排除單片機(jī)確實(shí)無數(shù)據(jù)發(fā)送的情況,再考慮是否由于沒有增加延時(shí),導(dǎo)致緩存區(qū)里沒有儲存到單片機(jī)發(fā)送的數(shù)據(jù)。
解決:在讀取串口數(shù)據(jù)之前增加延時(shí)語句。延時(shí)可import time,使用time庫中的time.sleep(sec),參數(shù)單位為秒。
補(bǔ)充:
- serial.iswaiting啟動接收,并返回接收數(shù)據(jù)的長度,然后用read(n)將這指定的數(shù)據(jù)讀出來。但現(xiàn)實(shí)中的問題是兩者的中間需要加延時(shí)(根據(jù)波特率計(jì)算發(fā)送內(nèi)容所需的時(shí)間,這樣就不會出現(xiàn)延時(shí)過短讀出的不全;延時(shí)時(shí)間長了就會出現(xiàn)前后幀發(fā)出的內(nèi)容重合到一起),此外如果需要判斷什么時(shí)候串口不活動,可以再serial.iswaiting一直延時(shí)(超過幾個(gè)字符的傳送時(shí)間,軟件延時(shí)計(jì)數(shù)器累加),而在循環(huán)體外將計(jì)數(shù)器清零,在累計(jì)的幾個(gè)字符時(shí)間接受的數(shù)據(jù)長度還為0則認(rèn)為通訊結(jié)束。鏈接
數(shù)據(jù)不全,有數(shù)據(jù)顯示,但缺少了內(nèi)容。
可能是單片機(jī)發(fā)送的時(shí)間長,延時(shí)時(shí)間比數(shù)據(jù)發(fā)送時(shí)間短,所以緩存中內(nèi)容只有顯示的那些數(shù)據(jù)。還可能是由于接受串口數(shù)據(jù)晚了,單片機(jī)發(fā)的數(shù)據(jù)沒及時(shí)存到緩存里。還可能是由于接收及顯示期間有中斷打斷該過程,執(zhí)行完畢后經(jīng)過一段時(shí)間,等到返回原程序處時(shí)已不能實(shí)現(xiàn)實(shí)時(shí)接收和顯示的功能。
解決:延時(shí)時(shí)間加長(延時(shí)期間不能進(jìn)行操作,為阻塞狀態(tài),不推薦),或考慮中斷返回后進(jìn)行判斷,進(jìn)一步處理,或建立多線程。
丟包
網(wǎng)絡(luò)丟包:
什么是丟包,為什么會丟包 - 知乎
數(shù)據(jù)丟包:
下位機(jī)、PC都有能力高速發(fā)送或接受數(shù)據(jù),但過高的傳輸速率(高波特率)意味著,中間的傳輸線路一旦受到干擾更容易發(fā)生電平不能及時(shí)轉(zhuǎn)換的問題。從幫助理解的角度,可以將數(shù)據(jù)看作一位一位的0/1組成的值,傳輸本身是高低電平的轉(zhuǎn)換,高電平代表1,低電平代表0。
數(shù)據(jù)丟包的原因:噪聲干擾、強(qiáng)磁場環(huán)境
間接原因:波特率過高,更易出錯(cuò)
解決:盡量在滿足應(yīng)用速度要求的前提下,低速率傳輸;采用可靠的協(xié)議;保持硬件穩(wěn)定。
數(shù)據(jù)顯示不全與數(shù)據(jù)丟包要區(qū)分開,丟包是在傳輸途中出現(xiàn)問題,顯示不全可能是由于丟包,也可能是由于上位機(jī)程序邏輯編寫錯(cuò)誤,或者單線程且處理數(shù)據(jù)緊接在接收數(shù)據(jù)之后,導(dǎo)致處理數(shù)據(jù)時(shí)接收值未顯示,而下次顯示時(shí)緩存中已被新數(shù)據(jù)覆蓋等等。
串口通信之?dāng)?shù)據(jù)丟失
串口通信丟失數(shù)據(jù)結(jié)局方案——C#_紫冰寒寞的專欄-CSDN博客_serialport 字符缺失
串口通信的一般思路是:先接收數(shù)據(jù),然后處理數(shù)據(jù),并在數(shù)據(jù)處理之后再次等待接收新的數(shù)據(jù)。但這種方法的缺點(diǎn)是,在串口高速率大信息量通信時(shí),會出現(xiàn)丟失數(shù)據(jù)的情況。
丟失數(shù)據(jù)的原因是數(shù)據(jù)接收和數(shù)據(jù)處理再同一個(gè)線程中,如果數(shù)據(jù)處理的時(shí)間太長,則來不及接收的數(shù)據(jù)只能暫存在緩存中。因此,一旦緩存滿了,新到的數(shù)據(jù)就會沖刷掉未來得及接收的數(shù)據(jù),從而造成數(shù)據(jù)的丟失。因此,只是增加緩存的容量不能解決數(shù)據(jù)丟失的根本問題。
解決思路:
- 數(shù)據(jù)接收與數(shù)據(jù)處理分別放在兩個(gè)線程中進(jìn)行;
- 數(shù)據(jù)接收線程:接收數(shù)據(jù)并將接收到的數(shù)據(jù)存入數(shù)據(jù)池中;
- 數(shù)據(jù)處理線程:從數(shù)據(jù)池中讀取數(shù)據(jù)和處理數(shù)據(jù);
注意:
- 由于兩個(gè)線程可能會同時(shí)訪問數(shù)據(jù)池,因此為了使數(shù)據(jù)接收得到最快的響應(yīng),最好不選用數(shù)組結(jié)構(gòu),而是選用隊(duì)列Queue作為數(shù)據(jù)池的數(shù)據(jù)結(jié)構(gòu)。
隊(duì)列在順序存儲方面非常有用。數(shù)據(jù)對象在隊(duì)列的一段插入,另一端移除。當(dāng)兩個(gè)線程同時(shí)訪問隊(duì)列時(shí),一個(gè)線程負(fù)責(zé)數(shù)據(jù)存入,另一個(gè)線程只負(fù)責(zé)操作數(shù)讀取,就會提高程序的運(yùn)行效率。
為何丟失數(shù)據(jù)量的大小不確定?
舉個(gè)例子,如果是由于單線程進(jìn)行讀取數(shù)據(jù)和處理數(shù)據(jù),那么處理數(shù)據(jù)期間就不能讀取,緩存區(qū)若溢出,則會被覆蓋。如果處理數(shù)據(jù)的操作和量是固定的,按道理會丟失定量的數(shù)據(jù),但實(shí)際上緩沖區(qū)中的數(shù)據(jù)量不一定,處理的數(shù)據(jù)量也不一定,讀取的速度也有不確定性,所以丟失的數(shù)據(jù)量也不會是恒定的。
如果讀取足夠快,或者次數(shù)足夠少,能夠不影響數(shù)據(jù)繼續(xù)寫入緩存區(qū),那么就能讀取完整的數(shù)據(jù),數(shù)據(jù)量等于發(fā)送量。
python相關(guān)
為什么要加if __name __==‘__main __’:
不寫也可以啟動,但最好加上,因?yàn)閕f __ name __ == ’ __ main __’的意思是:當(dāng).py文件被直接運(yùn)行時(shí),if __ name __ == ’ __ main __’之下的代碼塊將被運(yùn)行;當(dāng).py文件以模塊形式被導(dǎo)入時(shí),if __ name __ == ’ __ main __’之下的代碼塊不被運(yùn)行。
一些功能由于比較復(fù)雜,往往需要多人開發(fā),一個(gè)python程序?qū)?yīng)一個(gè)功能,為便于測試,每個(gè)功能程序下都有一個(gè)主函數(shù)。在主程序中,只需import功能程序所在文件,就可以調(diào)用功能py程序的函數(shù)(關(guān)于如何跨文件調(diào)用函數(shù)見本文目錄)。為了保證功能文件中的主函數(shù)不被導(dǎo)入到主函數(shù)中,就需要注釋掉每個(gè)功能程序中的主函數(shù),這十分的麻煩。因此python提供了if __name __==‘__main __’:條件,只要編寫主函數(shù)時(shí)均在此條件下編寫,就可以保證運(yùn)行哪個(gè)程序就用哪個(gè)主函數(shù)。
來自鏈接:https://blog.csdn.net/qq_25939803/article/details/98038106
線程
python多線程詳解 - luyuze95 - 博客園
鏈接目錄:
并發(fā)與并行
幾乎所有的操作系統(tǒng)都支持同時(shí)運(yùn)行多個(gè)任務(wù),每個(gè)任務(wù)通常是一個(gè)程序,每一個(gè)運(yùn)行中的程序就是一個(gè)進(jìn)程,即進(jìn)程是應(yīng)用程序的執(zhí)行實(shí)例。現(xiàn)代的操作系統(tǒng)幾乎都支持多進(jìn)程并發(fā)執(zhí)行。
- 并行指在同一時(shí)刻有多條指令在多個(gè)處理器(多核處理器)上同時(shí)執(zhí)行
- 并發(fā)是指在同一時(shí)刻只能有一條指令執(zhí)行,但多個(gè)進(jìn)程指令被快速輪換執(zhí)行,使得在宏觀上具有多個(gè)進(jìn)程同時(shí)執(zhí)行的效果。
線程與進(jìn)程
首先需要強(qiáng)調(diào)的是,線程和進(jìn)程對于開發(fā)一般的上位機(jī)串口助手不是必須的,尤其是對于操作系統(tǒng)不夠了解的新手來說,使用線程需要補(bǔ)充很多基礎(chǔ)知識,較為耗時(shí)。
對于一個(gè) CPU 而言,在某個(gè)時(shí)間點(diǎn)它只能執(zhí)行一個(gè)程序。也就是說,只能運(yùn)行一個(gè)進(jìn)程,CPU 不斷地在這些進(jìn)程之間輪換執(zhí)行。那么,為什么用戶感覺不到任何中斷呢?
這是因?yàn)橄鄬θ说母杏X來說,CPU 的執(zhí)行速度太快了(如果啟動的程序足夠多,則用戶依然可以感覺到程序的運(yùn)行速度下降了)。所以,雖然 CPU 在多個(gè)進(jìn)程之間輪換執(zhí)行,但用戶感覺到好像有多個(gè)進(jìn)程在同時(shí)執(zhí)行。
單線程與多線程
Python進(jìn)程和線程(包含兩者區(qū)別)
- 當(dāng)一個(gè)進(jìn)程里只有一個(gè)線程時(shí),叫作單線程。
- 一個(gè)進(jìn)程里超過一個(gè)線程就叫作多線程。
線程是進(jìn)程的組成部分,一個(gè)進(jìn)程可以擁有多個(gè)線程。在多線程中,會有一個(gè)主線程來完成整個(gè)進(jìn)程從開始到結(jié)束的全部操作,而其他的線程會在主線程的運(yùn)行過程中被創(chuàng)建或退出。
當(dāng)進(jìn)程被初始化后,主線程就被創(chuàng)建了,對于絕大多數(shù)的應(yīng)用程序來說,通常僅要求有一個(gè)主線程,但也可以在進(jìn)程內(nèi)創(chuàng)建多個(gè)順序執(zhí)行流,這些順序執(zhí)行流就是線程。
每個(gè)線程必須有自己的父進(jìn)程,且它可以擁有自己的堆棧、程序計(jì)數(shù)器和局部變量,但不擁有系統(tǒng)資源,因?yàn)樗透高M(jìn)程的其他線程共享該進(jìn)程所擁有的全部資源。線程可以完成一定的任務(wù),可以與其他線程共享父進(jìn)程中的共享變量及部分環(huán)境,相互之間協(xié)同完成進(jìn)程所要完成的任務(wù)。
線程的運(yùn)行是搶占式的,也就是說,當(dāng)前運(yùn)行的線程在任何時(shí)候都可能被掛起,以便另外一個(gè)線程可以運(yùn)行。
多線程也是并發(fā)執(zhí)行的,即同一時(shí)刻,Python 主程序只允許有一個(gè)線程執(zhí)行,這和全局解釋器鎖有關(guān)系,后續(xù)會做詳細(xì)介紹。
一個(gè)線程可以創(chuàng)建和撤銷另一個(gè)線程,同一個(gè)進(jìn)程中的多個(gè)線程之間可以并發(fā)運(yùn)行。
從邏輯的角度來看,多線程存在于一個(gè)應(yīng)用程序中,讓一個(gè)應(yīng)用程序可以有多個(gè)執(zhí)行部分同時(shí)執(zhí)行,但操作系統(tǒng)無須將多個(gè)線程看作多個(gè)獨(dú)立的應(yīng)用,對多線程實(shí)現(xiàn)調(diào)度和管理以及資源分配,線程的調(diào)度和管理由進(jìn)程本身負(fù)責(zé)完成。
常見異常類型
Python 常見異常類型 - Bactiy - 博客園
python 異常類型_Lapland的博客-CSDN博客
異常處理:
python中的異常及幾種常見異常_棠牧師的博客-CSDN博客
try: 功能,應(yīng)該做什么
except: 若有異常,做什么
重命名變量方法
右鍵變量名稱-> Refactor-> Rename
直接重命名所有同名變量。
運(yùn)算
原碼補(bǔ)碼轉(zhuǎn)換
代碼:
python——原碼轉(zhuǎn)補(bǔ)碼_cherry1307的博客-CSDN博客_python原碼轉(zhuǎn)補(bǔ)碼
- 源碼轉(zhuǎn)補(bǔ)碼或補(bǔ)碼轉(zhuǎn)源碼都可用同一步驟實(shí)現(xiàn)
- 何時(shí)轉(zhuǎn)換:有符號型二進(jìn)制數(shù)且符號位為1時(shí)才需要轉(zhuǎn)換
- 轉(zhuǎn)換步驟:除最高位1外,其余位取反得到反碼,反碼加1得補(bǔ)碼或原碼。
- 代碼:見上面的鏈接,親測可用,感謝博主
python指數(shù)**
例:求次方、根號、倒數(shù)
# 2的立方 print(2**3) # 8# 9開二次方根 print(9**(1/2)) # 3.0# 2平方的倒數(shù) print(2**(-2)) # 0.25數(shù)值與字符串
python讀取字符串長度len()
len()的參數(shù)只能是字符串類型。
例:
print(len('0b10001')) # 7python的數(shù)值與字符串區(qū)分
‘10001’:字符串
10001:十進(jìn)制
‘0b10001’:字符串
0b10001:二進(jìn)制
print(bin(17))顯示0b10001,沒問題。
不過,print(0b10001)顯示的是十進(jìn)制17,而不是0b10001,有人知道這是為什么嗎?
若有誤,歡迎指正留言。
python二進(jìn)制-十進(jìn)制轉(zhuǎn)換
python十進(jìn)制轉(zhuǎn)換為二進(jìn)制,八進(jìn)制_qq_37178232的博客-CSDN博客_十進(jìn)制6轉(zhuǎn)二進(jìn)制的計(jì)算過程python
十進(jìn)制轉(zhuǎn)二進(jìn)制:
bin()函數(shù),例子:17的二進(jìn)制數(shù)是10001,bin(17)為0b10001
bin函數(shù)得到二進(jìn)制字符串
注意:bin轉(zhuǎn)換的二進(jìn)制默認(rèn)最高位為1,高位的0會被去除,即0b類型。
注意:replace() 不會改變原 string 的內(nèi)容,要想改變需要重新賦值給原string。
二進(jìn)制轉(zhuǎn)十進(jìn)制:
注意:bin()轉(zhuǎn)換的結(jié)果是字符串,不能直接用int()轉(zhuǎn)換為十進(jìn)制整型,只有去除0b才可以,因?yàn)樽帜覆荒苻D(zhuǎn)換為int。
注意:默認(rèn)在int()中轉(zhuǎn)換的是無符號原碼,若有符號位要自行去除符號位并根據(jù)情況乘以-1(符號位為1,則需將除去符號位的原碼轉(zhuǎn)化為十進(jìn)制后再乘以-1);若為補(bǔ)碼,要自行判斷是否需要轉(zhuǎn)換為原碼(正數(shù)的原碼等于補(bǔ)碼)。
注意:要判斷二進(jìn)制位數(shù)是否有缺,尤其對于有符號位的二進(jìn)制,若缺位,容易將本來符號位為0的正數(shù)當(dāng)作符號位為1的負(fù)數(shù)處理。(字符串補(bǔ)零用str.zfill(n),將str數(shù)組總位數(shù)補(bǔ)到n位)
啰嗦一句,位數(shù)不夠或無符號位,就可以直接轉(zhuǎn)換;有符號位且位數(shù)齊全且符號位為1,則必須注意上述提醒。
python字符串轉(zhuǎn)十進(jìn)制整型
Python進(jìn)制轉(zhuǎn)換和補(bǔ)零_iridescent_mian的博客-CSDN博客_python hex 補(bǔ)0
(各種進(jìn)制轉(zhuǎn)換和類型轉(zhuǎn)換詳見鏈接)
從文檔中讀取的數(shù)據(jù)可能是string格式,運(yùn)算時(shí)需要轉(zhuǎn)化為可以計(jì)算的數(shù)值
注意:str字符串不能直接強(qiáng)制轉(zhuǎn)換為二進(jìn)制數(shù),要先轉(zhuǎn)換為十進(jìn)制后再轉(zhuǎn)換為二進(jìn)制。
str = "12345" num = int(str) # 轉(zhuǎn)為整型12345# num_bin = bin(str) # TypeError: 'str' object cannot be interpreted as an integer非數(shù)值字符串不能轉(zhuǎn)換,會報(bào)錯(cuò)。
python截取字符串
python按照指定字符或者長度 截取字符串 - pager - 博客園
截取字符串可以按照給定截取字符位置的方式截取:
如,a為一個(gè)字符串,則
a[0] 為字符串a(chǎn)從左往右數(shù)第1個(gè)字符
a[:1]為字符串a(chǎn)從左往右數(shù)第1個(gè)字符
a[1:]為字符串a(chǎn)從左往右數(shù)從第2個(gè)字符開始的所有字符
a[-1:]為字符串a(chǎn)從右往左數(shù)第1個(gè)字符
a[:-1]為字符串a(chǎn)從右往左數(shù)第2個(gè)字符開始的所有字符(順序不變)
例:
a = "Hello"print "a[1:4] 輸出結(jié)果:", a[1:4] #結(jié)果 ell print "a[:4] 輸出結(jié)果:", a[:4] #結(jié)果 Hell print "a[1:] 輸出結(jié)果:", a[1:] #結(jié)果 ello print "a[-1:] 輸出結(jié)果:", a[-1:] #結(jié)果o print "a[:-1] 輸出結(jié)果:", a[:-1] #結(jié)果Hell截取字符串也可以按照給定截取字符標(biāo)志的方式截取:
即根據(jù)特定字符為界,截取特定字符之前或之后的字符串。
例:
a = "Hello" symbol = 'e' # 截取字符標(biāo)志# 截取e字符左半部分 a_l = a[:a.index(symbol)] # 截取e字符右半部分,包括e a_r = a[a.index(symbol):]print(a_l) #結(jié)果 H print(a_r) #結(jié)果 ello注:截取字符標(biāo)志也可以是’\t’等符號。
python 替換字符串
temp_str = 'this is a test' print(temp_str.replace('is','IS') print(temp_str) # 輸出 # thIS IS a test # this is a testtemp_str = temp_str.replace('is','IS') print(temp_str) # 輸出 # thIS IS a test注意:replace() 不會改變原 string 的內(nèi)容,要想改變需要重新賦值給原string。
列表插入元素append
python中沒有數(shù)組的數(shù)據(jù)結(jié)構(gòu),可以用列表代替。
列表的聲明:
# 聲明一個(gè)空列表 a = [] # 聲明一個(gè)列表 b = ['3', '4']插入元素:
# 創(chuàng)建列表并增加元素 a = ['!3'] a.append('a') a.append('bc') a.append('123') print(a) # ['!3', 'a', 'bc', '123']# 將第4個(gè)元素切片(截取) a[3] = a[3][2:] print(a) # ['!3', 'a', 'bc', '3']python 二維列表
# 聲明一維列表 list1 = []# 聲明二維列表list1,list1含1個(gè)列表元素 list1.append([]) list1[0].append('1') list1[0].append(2) # 聲明二維列表list1,list1含2個(gè)列表元素 list1.append([]) list1[1].append('3') list1[1].append('4') # 聲明二維列表list1,list1含3個(gè)列表元素 list1.append([]) list1[2].append('567')print(len(list1)) print(list1) print(str(list1)) print(int(list1[2][0]))# 結(jié)果: # 3 # [['1', 2], ['3', '4'], ['567']] # [['1', 2], ['3', '4'], ['567']] # 567python二維列表對應(yīng)元素相加
Python之list對應(yīng)元素求和的方法_python_腳本之家
方法1:直接用for循環(huán)相加
方法2:用numpy模塊定義數(shù)組,數(shù)組1+數(shù)組2
方法3:用numpy模塊定義數(shù)組,用sum()函數(shù)
encode與decode
decode的作用是將其他編碼的字符串轉(zhuǎn)換成Unicode編碼,如str1.decode(‘gb2312’),表示將gb2312編碼的字符串str1轉(zhuǎn)換成Unicode編碼。
encode的作用是將unicode編碼轉(zhuǎn)換成其他編碼的字符串,如str2.encode(‘gb2312’),表示將Unicode編碼的字符串str2轉(zhuǎn)換成gb2312編碼。
str1.decode(‘utf-8’):將utf-8編碼的字符串str1轉(zhuǎn)換成Unicode編碼。
文件
讀寫文件(txt、csv、excel)
Python讀寫文件(csv、txt、excel) - 簡書
讀寫均由open()實(shí)現(xiàn),結(jié)束后要close()關(guān)閉文件。
例:讀text文件
# 以讀的模式打開文件 f = open('C:/Users/Administrator/Desktop/output.txt', mode='r')# 讀取數(shù)據(jù),讀取方式有三種 ftext1 = f.read() # 一次性讀取完成 ftext2 = f.readlines() # 同上 ftext3 = f.readline() # 只讀取1行# 關(guān)閉 f.close()例:寫text文件
# 以寫的模式打開文件 f = open('C:/Users/Administrator/Desktop/input.txt', mode='w')# 寫入數(shù)據(jù) ftext1 = f.write('hello!') # 一次性讀取完成# 關(guān)閉 f.close()with open :
由于文件讀寫時(shí)都有可能產(chǎn)生IOError,一旦出錯(cuò),后面的f.close()就不會調(diào)用。所以,為了保證無論是否出錯(cuò)都能正確地關(guān)閉文件,我們可以使用try … finally來實(shí)現(xiàn),但是每次都這么寫實(shí)在太繁瑣,所以,Python引入了with語句來自動幫我們調(diào)用close()方法:
補(bǔ)充:Python 將數(shù)據(jù)寫入文件(txt、csv、excel)_菲宇運(yùn)維-CSDN博客
文件操作模式
'w’模式下,每次寫入都會覆蓋原內(nèi)容,若不想覆蓋原內(nèi)容,則用’a’模式。
python跨文件調(diào)用函數(shù)
python 一個(gè).py文件如何調(diào)用另一個(gè).py文件中的類和函數(shù)_winycg的博客-CSDN博客_python 引用另一個(gè)py文件
親測可行,感謝博主
datetime庫 獲取當(dāng)前時(shí)間
python獲取當(dāng)前時(shí)間的用法 - 七月曉曉翁 - 博客園
datetime.datetime.now()
import datetime t_name = datetime.datetime.strftime(datetime.datetime.now(), '%m%d_%M:%S') print(t_name) # 0727_31:12實(shí)例鏈接
計(jì)算器GUI實(shí)例
python帶界面的計(jì)算器_qq_24624539的博客-CSDN博客_python計(jì)算器
可供小白學(xué)習(xí)快速熟悉python開發(fā)GUI。
串口調(diào)試助手GUI實(shí)例
python實(shí)現(xiàn)串口通訊小程序(GUI界面)_明志的博客-CSDN博客_pycharm 開發(fā)串口
該實(shí)例能夠滿足最基礎(chǔ)的串口調(diào)試功能,發(fā)送命令和接收命令需手動操作。還能夠?qū)崿F(xiàn)串口自動讀取連接。
讀取串口數(shù)據(jù)并寫入txt文件
python讀取串口數(shù)據(jù)并寫入txt文件
總結(jié)
以上是生活随笔為你收集整理的python3 GUI用户界面总结(以串口调试为例,持续改进)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 飞机进度条
- 下一篇: python爬虫笔记(八) 实例3:用P