python 打包exe程式
阿新 • • 發佈:2020-08-28
安裝python環境
https://www.python.org/downloads/windows/
安裝pyinstaller
pip install pyinstaller
準備python原始碼
from tkinter import Tk from tkinter import Button from tkinter import INSERT from tkinter import END from tkinter import WORD from tkinter import BOTH from tkinter.scrolledtext import ScrolledText import tkinter.filedialog import tkinter.messagebox import xml.dom.minidom import os import re import string g_timeout = 4 # 4秒超時 # 通訊引數 g_param = { "ProtocolType": "0x00", "PHYPort": "0x00", "FunctionAddress": "0x00", "ECUAddress": "0x00", "TesterAddress": "0xF1", "Baudrate": "500", "TIdle": "300", "TWup": "50", "P1Min": "0", "P1Max": "20", "P2Min": "25", "P2Max": "50", "P3Min": "55", "P3Max": "5000", "P4Min": "5", "P4Max": "20", "CanPhysReqId": "0x710", "CanFuncReqId": "0x7DF", "Equipment_Serv_Id": "0x00", "Ecu_Time_T1": "0x00", "Ecu_Time_T2": "0x00", "Ecu_Time_T3": "0x00", "Ecu_Time_T4": "0x00", "Tester_Time_T1": "0x00", "Tester_Time_T2": "0x00", "Tester_Time_T3": "0x00", "Tester_Time_T4": "0x00", } # 日誌中解析的報文結構 class Packet: id = "" thread = "" process = "" time = 0 content = [] content_string = "" valid = True def __init__(self, id, thread, process ,content, content_string, time): self.id = id self.thread = thread self.process = process self.content = content self.content_string = content_string self.time = time # 對應xml class Service: req = "" res = "" def __init__(self, req, res): self.req = req self.res = res # 對應xml class Section: name = "" sid = "" rid = "" services = [] def __init__(self, sid, rid): self.name = sid + "_" + rid self.sid = sid self.rid = rid self.services = [] class Main(): packets = [] xmlFile = [] def __init__(self): self.win = Tk() self.initWin() self.log = ScrolledText(self.win, wrap=WORD, height=40) self.log.pack(side="bottom", fill=BOTH) self.initBtn() self.win.mainloop() def initWin(self): self.win.title("Log") self.win.geometry("600x600") self.win.resizable(width=False,height=False) def initBtn(self): Button(self.win, text="選擇日誌檔案..", command=self.GetResource).place(x=10, y=10) Button(self.win, text="匯出結果檔案", command=self.GenerateXML).place(x=110, y=10) # 開啟檔案 獲取所有報文內容 def GetResource(self): default_dir = r"C:\\" self.filePath = tkinter.filedialog.askopenfilename(title=u'選擇檔案', initialdir=(os.path.expanduser(default_dir))) try: f= open(self.filePath, 'r', encoding='UTF-8', errors='ignore') except IOError as e: Tk.messagebox.showerror(title = '錯誤', message='開啟檔案失敗') return patternPacket = re.compile('^[A-Z]+ ([0-9]*) (?P<time>[0-9]*)\.([0-9]*) (?P<thread_num>[a-zA-Z0-9]*)::(?P<process_num>[a-zA-Z0-9]*) \[([a-zA-Z]*)\] OS[<|>] (?P<id>[a-zA-Z0-9]*) (?P<content>[^"]*)') patternOdbParam = re.compile('^[A-Z]+ ([0-9]*) ([0-9]*)\.([0-9]*) ([a-zA-Z0-9]*)::([a-zA-Z0-9]*) \[([a-zA-Z]*)\] ObdOpen\(port=([0-9]*),proto=([0-9]*),rate=([a-zA-Z0-9]*),fadr=([a-zA-Z0-9]*),eadr=([a-zA-Z0-9]*),tadr=([a-zA-Z0-9]*),sid=0x(?P<sid>[a-zA-Z0-9]*),rid=0x(?P<rid>[a-zA-Z0-9]*)\)') self.log.delete(0.0, END) lines = f.readlines() for line in lines: if (-1 != line.find("[vcicore] ObdOpen(port=")): regMatch = patternOdbParam.match(line) if None != regMatch: linebits = regMatch.groupdict() sid = linebits['sid'] rid = linebits['rid'] # 去重 if (self.RemoveDuplication(sid, rid)): section = Section(sid, rid) self.xmlFile.append(section) if (-1 != line.find("[vcicore] OS")): regMatch = patternPacket.match(line) if None != regMatch: linebits = regMatch.groupdict() content_string = content = linebits['content'].replace("\n","") content = content_string.split(' ') # 36刷寫報文只取部分 if (len(content) > 20 and content[0] == "36"): content = content[:3] content_string = content_string[:8] packet = Packet(linebits['id'], linebits['thread_num'], linebits['process_num'], content, content_string, int(linebits['time'])) self.log.insert(INSERT, linebits['id']+ " " +content_string +'\n') self.packets.append(packet) f.close() # 生成xml檔案 def GenerateXML(self): cnt = 0 for element in self.xmlFile: self.Organize(element) if (len(element.services) != 0): self.CreateFile(element) cnt = cnt + 1 tkinter.messagebox.showwarning(title = '完成',message='共生成'+str(cnt)+'個檔案') self.filePath = "" # 判斷是否重複 def RemoveDuplication(self, sid, rid): for e in self.xmlFile: if (sid == e.sid and rid == e.rid): return False return True # 驗證是否是對應的收發報文 def Calibrate(self, req, res): if (req.process == res.process and req.thread == res.thread): if (len(req.content) > 0 and len(res.content) > 0): if (res.content[0] == "7F"): #7F的特殊情況 return True if (64 == int(res.content[0], 16) - int(req.content[0], 16)): return True return False # 整理報文對應的檔案 def Organize(self, section): cnt_record = 0 while (True): if (0 == len(self.packets)): break # 報文列表為空,退出 #找到一個傳送id cnt_sid = -1 index = cnt_record while (index < len(self.packets)): if (self.packets[index].valid and section.sid == self.packets[index].id): cnt_sid = index #找到的傳送報文設定無效標記 self.packets[index].valid = False break index += 1 cnt_record = index #sid未找到,列表中沒有需要的報文,退出 if (-1 == cnt_sid): break #找到報文傳送id對應的接收id cnt_rid = -1 index = cnt_sid + 1 sid_head = self.packets[cnt_sid].content[0] #傳送報文的頭部 max_time = self.packets[cnt_sid].time + g_timeout #最大尋找時間 while (index < len(self.packets)): if (self.packets[index].valid and section.rid == self.packets[index].id and self.packets[index].time < max_time): #判斷是延時幀(7F xx 78) if (len(self.packets) > 2 and self.packets[index].content[0] == "7F" and self.packets[index].content[1] == sid_head and self.packets[index].content[2] == "78"): max_time = self.packets[index].time + g_timeout # 更新超時時間,以當前78報文為準 self.packets[index].valid = False # 78報文設定無效標記 index += 1 continue if (self.Calibrate(self.packets[cnt_sid], self.packets[index])): # 通過執行緒號等驗證是否是對應的接收報文 cnt_rid = index # 找到了接收的報文 break index += 1 #rid未找到,超時 if (-1 == cnt_rid): continue #新增列表 svc = Service(self.packets[cnt_sid].content_string, self.packets[cnt_rid].content_string) self.log.see(END) section.services.append(svc) self.packets[cnt_rid].valid = False # 建立xml檔案 def CreateFile(self, resultFile): impl = xml.dom.minidom.getDOMImplementation() # 設定根結點 dom = impl.createDocument(None, 'ECU', None) root = dom.documentElement root.setAttribute("name", resultFile.name) # 根節點新增子節點COMMPARAMETERS commparameters = dom.createElement('COMMPARAMETERS') root.appendChild(commparameters) # 設定通訊引數 for key, value in g_param.items(): nameE=dom.createElement('PARAM') nameE.setAttribute("name", key) nameE.setAttribute("value", value) commparameters.appendChild(nameE) # 設定canid nameE=dom.createElement('PARAM') nameE.setAttribute("name", "CANSID") nameE.setAttribute("value",resultFile.sid) commparameters.appendChild(nameE) nameE=dom.createElement('PARAM') nameE.setAttribute("name", "CANRID") nameE.setAttribute("value", resultFile.sid) commparameters.appendChild(nameE) # 根節點新增子節點SECTIONS sections = dom.createElement('SECTIONS') root.appendChild(sections) # SECTION section=dom.createElement('SECTION') sections.appendChild(section) for svc in resultFile.services: #SERVICE service=dom.createElement('SERVICE') section.appendChild(service) #REQ req=dom.createElement('REQ') reqTxt=dom.createTextNode(svc.req) #內容 req.appendChild(reqTxt) service.appendChild(req) #RES res=dom.createElement('RES') resTxt=dom.createTextNode(svc.res) #內容 res.appendChild(resTxt) service.appendChild(res) f= open(resultFile.name + '.xml', 'w') #w替換為a,追加 dom.writexml(f, addindent='\t', newl='\n') f.close() if __name__ == '__main__': Main()
打包程式
# -w 隱藏控制檯
pyinstaller -F -w program.py