需求:
将类似如下xml文件的externalid节点值修改成不重复的值
实现该功能的代码Func.py:
1 #coding=utf-8 2 ''' 3 Created on 2019年10月15日 4 5 @author: yanerfree 6 7 ''' 8 import re 9 import sys 10 11 '''******************************************************** 12 Func Name: modifyData 13 Para: path : xml文件路径 14 num : 起始值从num开始,依次递增1 15 savepath : 修改后的文件保存路径 16 return: 17 Desc: 修改xml中<externalid>节点中的值,使其每一条都不同 18 Date: 20191015 19 Auth: yanerfree 20 ********************************************************''' 21 def modifyData(path, num, savepath): 22 num_externalid = int(num) 23 f1 = open(path,'r', encoding='utf-8') 24 line = f1.readline() 25 #[在re中有特殊含义,需要转义 26 pattern = re.compile(r's*<externalid><![CDATA[d+]]></externalid>') 27 28 f2 = open(savepath, 'w', encoding='utf-8') 29 30 while line: 31 #print('num_externalid:',num_externalid) 32 m = re.match(pattern, line, flags=0)#没匹配到返回None 33 #print(m) 34 if m: 35 print('替换<externalid>') 36 37 line = re.sub('d+', str(num_externalid), line) 38 #line = ' <externalid><![CDATA[%d]]></externalid> '%num 39 num_externalid += 1 40 41 print(line) 42 f2.write(line) 43 line = f1.readline() 44 45 f1.close() 46 f2.close() 47 48 def testMatch(): 49 pattern = re.compile(r's*<externalid><![CDATA[d+]]></externalid>') 50 s1 = '<externalid><![CDATA[1110]]></externalid>' 51 p1 = '<externalid><![CDATA'#[在re中有特殊含义,需要转义 52 s2 = 'aasffdafaaa' 53 p2 = 'a' 54 m = re.match(pattern, s1, flags=0)#没匹配到返回None 55 print(m) 56 print(m.group(0)) 57 58 59 def testFindAll(): 60 s1='2019-09-16 01:18:58 INFO [nioEventLoopGroup-3-7] [SimpleServerHandler.java:45] - client id:1568567938696,client request ip:183.195.12.193,content:SN=56636200000679;MODE=1;TIME=2019-9-16 1:19:1;LOC=0-460,0,6350,53537,40,16,0,0-460,0,6350,53537,40,16,0,0-460,0,6350,53537,40,16,0,0;TEST_NUM=4091;LOC_ERR=410;CONN_ERR=3400;SEND_ERR=0;REC_ERR=0' 61 pattern = re.compile('content:SN=(.*?);MODE=(.*?);TIME=(.*?) .*?LOC=(.*?);TEST_NUM=(.*?);LOC_ERR=(.*?);CONN_ERR=(.*?);SEND_ERR=(.*?);REC_ERR=(d*)' ) 62 res = re.findall(pattern, s1) 63 print(res) 64 65 ''' 66 运行结果: 67 [('56636200000679', '1', '2019-9-16', '0-460,0,6350,53537,40,16,0,0-460,0,6350,53537,40,16,0,0-460,0,6350,53537,40,16,0,0', '4091', '410', '3400', '0', '0')] 68 ''' 69 def testresub(): 70 num=9009 71 line = ' <externalid><![CDATA[1]]></externalid>' 72 line = re.sub('d+', str(num), line) 73 print(line) 74 75 if __name__ == '__main__': 76 #''' 77 fp = './test001.xml' 78 sp = './output001.xml' 79 num = 10 80 modifyData(fp, num ,sp) 81 #''' 82 #testMatch() 83 #testFindAll() 84 #testresub() 85 86 87
以上代码单纯实现了需要的功能,但是如果需要给大家使用,不可能让所有人都安装python3环境,并且还安装需要的包,
所以将其进一步开发并打包成exe可执行文件
实现代码 modifyXmldata.py:
1 #coding=utf-8 2 ''' 3 Created on 2019年10月15日 4 5 @author: yanerfree 6 ''' 7 from PyQt5.QtGui import * 8 from PyQt5.QtWidgets import * 9 from PyQt5.QtCore import * 10 import sys 11 import os 12 import time 13 14 from Func import * 15 16 class windowtool(QMainWindow): 17 def __init__(self): 18 super().__init__() 19 self.setupUi() 20 21 def setupUi(self): 22 self.setWindowTitle("MyTool - modify externalid")#设置窗体标题 23 self.resize(600,500)#设置窗体大小 24 self.setFixedWidth(600)#固定窗体宽度 25 #self.setFixedSize(600,500)#固定窗体大小 26 self.createMenu()#菜单 27 self.createWidget()#创建组件Widget 28 self.createStatusBar()#创建状态栏 29 30 def createMenu(self): 31 menubar = self.menuBar()##实例化主窗口的QMenuBar对象 32 #向菜单栏中添加新的QMenu对象,父菜单 33 menu_file = menubar.addMenu("File") 34 menu_file.addAction(QAction("Exit",self,triggered=qApp.quit)) 35 36 menu_Help = menubar.addMenu("Help") 37 menu_Help.addAction(QAction("About",self,triggered=self.about)) 38 39 def createWidget(self): 40 #全局控件(注意参数self),用于承载全局布局 41 self.wwidget = QWidget(self) 42 self.wwidget.move(20,40) 43 self.wwidget.resize(500,400) 44 #全局布局(注意参数wwidget) 45 self.wholelayout = QVBoxLayout(self.wwidget) 46 47 #局部布局-网格布局 48 glayout = QGridLayout() 49 glayout.setSpacing(10) 50 ###*******************************************### 51 label1 = QLabel('选择需要处理的文件(xml):') 52 button1 = QPushButton("选择文件") 53 button1.clicked.connect(self.selectxmlfile) 54 55 self.label_filepath = QLabel() 56 self.label_filepath.setFrameStyle(QFrame.Panel|QFrame.Sunken) 57 58 label3 = QLabel('选择文件处理后存放位置:') 59 button2 = QPushButton("选择路径") 60 button2.clicked.connect(self.choosedir) 61 62 self.label_savepath = QLabel() 63 self.label_savepath.setFrameStyle(QFrame.Panel|QFrame.Sunken) 64 65 label5 = QLabel('设置 <externalid> 起始值 (整数):') 66 self.linedit_num = QLineEdit() 67 68 button_clear = QPushButton("Clear") 69 button_clear.clicked.connect(self.clean_textedit) 70 self.textedit_info = QTextEdit() 71 72 startbutton = QPushButton("Start") 73 startbutton.clicked.connect(self.start) 74 75 glayout.addWidget(label1,1,1,1,2)#(1,1)一行一列 76 glayout.addWidget(button1,2,1,1,1) 77 glayout.addWidget(self.label_filepath,2,2,1,7) 78 glayout.addWidget(label3,3,1,1,2) 79 glayout.addWidget(button2,4,1,1,1) 80 glayout.addWidget(self.label_savepath,4,2,1,7) 81 glayout.addWidget(label5,5,1,1,2) 82 glayout.addWidget(self.linedit_num,5,3,1,2) 83 glayout.addWidget(startbutton,6,1,1,1) 84 glayout.addWidget(button_clear,7,8) 85 glayout.addWidget(self.textedit_info,8,1,8,8) 86 ###*******************************************### 87 88 89 self.wholelayout.addLayout(glayout) 90 91 def createStatusBar(self): 92 #实例化状态栏 93 self.statusBar=QStatusBar() 94 self.statusBar.showMessage("This is status info",4000) 95 96 #设置状态栏,类似布局设置 97 self.setStatusBar(self.statusBar) 98 99 def selectxmlfile(self): 100 fileName,fileType = QFileDialog.getOpenFileName(self, 101 "Choose xml file", 102 r"C:\", 103 "Text Files (*.xml);;Text Files (*.txt);;")#设置文件扩展名过滤 104 105 fileName = fileName.replace('/','\')#windows下需要进行文件分隔符转换 106 print(fileName) 107 self.label_filepath.setText(fileName) 108 self.label_savepath.setText('') 109 #return(fileName) 110 111 def choosedir(self): 112 filed,filen = os.path.split(self.label_filepath.text()) 113 savedir = QFileDialog.getExistingDirectory(self,"choose directory to save file",filed) 114 #print(savedir) 115 if not os.path.exists(savedir): 116 return 117 savedir = savedir.replace('/','\')#windows下需要进行文件分隔符转换 118 filen = time.strftime('%Y%m%d%H%M%S',time.localtime(time.time()))+'_'+ filen 119 savedir = os.path.join(savedir, filen) 120 self.label_savepath.setText(savedir) 121 #print(savedir) 122 123 def start(self): 124 num = self.linedit_num.text() 125 fp = self.label_filepath.text() 126 sp = self.label_savepath.text() 127 text = '-'*20+' ' 128 text += '文件处理完成'+' ' 129 text += '处理后文件:'+' ' 130 text += sp+' ' 131 if num and fp and sp: 132 modifyData(fp, num, sp) 133 #print(self.textedit_info.toPlainText()) 134 self.textedit_info.setText(text+self.textedit_info.toPlainText()) 135 136 else: 137 QMessageBox.warning(self,"Warring","请确认设置项是否全部设置完成",QMessageBox.Yes|QMessageBox.No,QMessageBox.Yes) 138 139 def about(self): 140 pass 141 142 def clean_textedit(self): 143 self.textedit_info.clear() 144 145 146 147 if __name__ == '__main__': 148 # 每一个pyqt程序中都需要有一个QApplication对象,sys.argv是一个命令行参数列表 149 app = QApplication(sys.argv) 150 #实例化窗口 151 demo = windowtool() 152 #显示 153 demo.show() 154 #进入程序的主循环,遇到退出情况,终止程序 155 sys.exit(app.exec_()) 156 157 158 159 160
最后将其打包成exe可执行文件:
需要安装PyInstaller,如未安装,可直接用pip安装即可
命令:pip install PyInstaller
使用pyinstaller打包
打开cmd窗口,把路径切换到文件所在路径,输入以下内容(最后的是文件名):
pyinstaller -F modifyXmldata.py
或者直接全路径打包,不需要在cmd中将路径切换到脚本所在路径:
pyinstaller -F F: estmodifyXmldata.py
另,打包时可以添加参数:
pyinstaller -F F: estmodifyXmldata.py
pyinstaller -F -w F: estmodifyXmldata.py
参数含义
-F 表示生成单个可执行文件
-w 表示去掉控制台窗口,这在GUI界面时非常有用。不过如果是命令行程序的话那就把这个选项删除吧!
-p 表示你自己自定义需要加载的类路径,一般情况下用不到
-i 表示可执行文件的图标
给程序换图标的方法
输入命令中添加一个-i tubiao.ico(图标的相对路径)。
pyinstaller -F -i tubiao123.ico F: estmodifyXmldata.py
注意
--需要将程序打包在哪里,就在哪里打开cmd(按住shift键 然后右键,在此处打开cmd窗口)
--有些资源文件如图片等,可直接复制到exe所在的目录下,否则会报错找不到
完成后的效果: