pyqt5_实例:修改xml文件中节点值

时间:2023-03-09 14:33:17
pyqt5_实例:修改xml文件中节点值

需求:

将类似如下xml文件的externalid节点值修改成不重复的值

pyqt5_实例:修改xml文件中节点值

实现该功能的代码Func.py:

 #coding=utf-8
'''
Created on 2019年10月15日 @author: yanerfree '''
import re
import sys '''********************************************************
Func Name: modifyData
Para: path : xml文件路径
num : 起始值从num开始,依次递增1
savepath : 修改后的文件保存路径
return:
Desc: 修改xml中<externalid>节点中的值,使其每一条都不同
Date: 20191015
Auth: yanerfree
********************************************************'''
def modifyData(path, num, savepath):
num_externalid = int(num)
f1 = open(path,'r', encoding='utf-8')
line = f1.readline()
#[在re中有特殊含义,需要转义
pattern = re.compile(r'\s*<externalid><!\[CDATA\[\d+\]\]></externalid>') f2 = open(savepath, 'w', encoding='utf-8') while line:
#print('num_externalid:',num_externalid)
m = re.match(pattern, line, flags=0)#没匹配到返回None
#print(m)
if m:
print('替换<externalid>') line = re.sub('\d+', str(num_externalid), line)
#line = ' <externalid><![CDATA[%d]]></externalid>\r\n'%num
num_externalid += 1 print(line)
f2.write(line)
line = f1.readline() f1.close()
f2.close() def testMatch():
pattern = re.compile(r'\s*<externalid><!\[CDATA\[\d+\]\]></externalid>')
s1 = '<externalid><![CDATA[1110]]></externalid>'
p1 = '<externalid><!\[CDATA'#[在re中有特殊含义,需要转义
s2 = 'aasffdafaaa'
p2 = 'a'
m = re.match(pattern, s1, flags=0)#没匹配到返回None
print(m)
print(m.group(0)) def testFindAll():
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'
pattern = re.compile('content:SN=(.*?);MODE=(.*?);TIME=(.*?) .*?LOC=(.*?);TEST_NUM=(.*?);LOC_ERR=(.*?);CONN_ERR=(.*?);SEND_ERR=(.*?);REC_ERR=(\d*)' )
res = re.findall(pattern, s1)
print(res) '''
运行结果:
[('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')]
'''
def testresub():
num=9009
line = ' <externalid><![CDATA[1]]></externalid>'
line = re.sub('\d+', str(num), line)
print(line) if __name__ == '__main__':
#'''
fp = './test001.xml'
sp = './output001.xml'
num = 10
modifyData(fp, num ,sp)
#'''
#testMatch()
#testFindAll()
#testresub()

以上代码单纯实现了需要的功能,但是如果需要给大家使用,不可能让所有人都安装python3环境,并且还安装需要的包,

所以将其进一步开发并打包成exe可执行文件

实现代码 modifyXmldata.py:

 #coding=utf-8
'''
Created on 2019年10月15日 @author: yanerfree
'''
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
import sys
import os
import time from Func import * class windowtool(QMainWindow):
def __init__(self):
super().__init__()
self.setupUi() def setupUi(self):
self.setWindowTitle("MyTool - modify externalid")#设置窗体标题
self.resize(600,500)#设置窗体大小
self.setFixedWidth(600)#固定窗体宽度
#self.setFixedSize(600,500)#固定窗体大小
self.createMenu()#菜单
self.createWidget()#创建组件Widget
self.createStatusBar()#创建状态栏 def createMenu(self):
menubar = self.menuBar()##实例化主窗口的QMenuBar对象
#向菜单栏中添加新的QMenu对象,父菜单
menu_file = menubar.addMenu("File")
menu_file.addAction(QAction("Exit",self,triggered=qApp.quit)) menu_Help = menubar.addMenu("Help")
menu_Help.addAction(QAction("About",self,triggered=self.about)) def createWidget(self):
#全局控件(注意参数self),用于承载全局布局
self.wwidget = QWidget(self)
self.wwidget.move(20,40)
self.wwidget.resize(500,400)
#全局布局(注意参数wwidget)
self.wholelayout = QVBoxLayout(self.wwidget) #局部布局-网格布局
glayout = QGridLayout()
glayout.setSpacing(10)
###*******************************************###
label1 = QLabel('选择需要处理的文件(xml):')
button1 = QPushButton("选择文件")
button1.clicked.connect(self.selectxmlfile) self.label_filepath = QLabel()
self.label_filepath.setFrameStyle(QFrame.Panel|QFrame.Sunken) label3 = QLabel('选择文件处理后存放位置:')
button2 = QPushButton("选择路径")
button2.clicked.connect(self.choosedir) self.label_savepath = QLabel()
self.label_savepath.setFrameStyle(QFrame.Panel|QFrame.Sunken) label5 = QLabel('设置 <externalid> 起始值 (整数):')
self.linedit_num = QLineEdit() button_clear = QPushButton("Clear")
button_clear.clicked.connect(self.clean_textedit)
self.textedit_info = QTextEdit() startbutton = QPushButton("Start")
startbutton.clicked.connect(self.start) glayout.addWidget(label1,1,1,1,2)#(1,1)一行一列
glayout.addWidget(button1,2,1,1,1)
glayout.addWidget(self.label_filepath,2,2,1,7)
glayout.addWidget(label3,3,1,1,2)
glayout.addWidget(button2,4,1,1,1)
glayout.addWidget(self.label_savepath,4,2,1,7)
glayout.addWidget(label5,5,1,1,2)
glayout.addWidget(self.linedit_num,5,3,1,2)
glayout.addWidget(startbutton,6,1,1,1)
glayout.addWidget(button_clear,7,8)
glayout.addWidget(self.textedit_info,8,1,8,8)
###*******************************************### self.wholelayout.addLayout(glayout) def createStatusBar(self):
#实例化状态栏
self.statusBar=QStatusBar()
self.statusBar.showMessage("This is status info",4000) #设置状态栏,类似布局设置
self.setStatusBar(self.statusBar) def selectxmlfile(self):
fileName,fileType = QFileDialog.getOpenFileName(self,
"Choose xml file",
r"C:\\",
"Text Files (*.xml);;Text Files (*.txt);;")#设置文件扩展名过滤 fileName = fileName.replace('/','\\')#windows下需要进行文件分隔符转换
print(fileName)
self.label_filepath.setText(fileName)
self.label_savepath.setText('')
#return(fileName) def choosedir(self):
filed,filen = os.path.split(self.label_filepath.text())
savedir = QFileDialog.getExistingDirectory(self,"choose directory to save file",filed)
#print(savedir)
if not os.path.exists(savedir):
return
savedir = savedir.replace('/','\\')#windows下需要进行文件分隔符转换
filen = time.strftime('%Y%m%d%H%M%S',time.localtime(time.time()))+'_'+ filen
savedir = os.path.join(savedir, filen)
self.label_savepath.setText(savedir)
#print(savedir) def start(self):
num = self.linedit_num.text()
fp = self.label_filepath.text()
sp = self.label_savepath.text()
text = '-'*20+'\r\n'
text += '文件处理完成'+'\r\n'
text += '处理后文件:'+'\r\n'
text += sp+'\r\n'
if num and fp and sp:
modifyData(fp, num, sp)
#print(self.textedit_info.toPlainText())
self.textedit_info.setText(text+self.textedit_info.toPlainText()) else:
QMessageBox.warning(self,"Warring","请确认设置项是否全部设置完成",QMessageBox.Yes|QMessageBox.No,QMessageBox.Yes) def about(self):
pass def clean_textedit(self):
self.textedit_info.clear() if __name__ == '__main__':
# 每一个pyqt程序中都需要有一个QApplication对象,sys.argv是一个命令行参数列表
app = QApplication(sys.argv)
#实例化窗口
demo = windowtool()
#显示
demo.show()
#进入程序的主循环,遇到退出情况,终止程序
sys.exit(app.exec_())

最后将其打包成exe可执行文件:

需要安装PyInstaller,如未安装,可直接用pip安装即可

命令:pip install PyInstaller

使用pyinstaller打包

打开cmd窗口,把路径切换到文件所在路径,输入以下内容(最后的是文件名):

pyinstaller -F modifyXmldata.py

或者直接全路径打包,不需要在cmd中将路径切换到脚本所在路径:

pyinstaller -F  F:\test\modifyXmldata.py

另,打包时可以添加参数:

pyinstaller -F F:\test\modifyXmldata.py

pyinstaller -F -w F:\test\modifyXmldata.py

参数含义

-F 表示生成单个可执行文件

-w 表示去掉控制台窗口,这在GUI界面时非常有用。不过如果是命令行程序的话那就把这个选项删除吧!

-p 表示你自己自定义需要加载的类路径,一般情况下用不到

-i 表示可执行文件的图标

给程序换图标的方法

输入命令中添加一个-i tubiao.ico(图标的相对路径)。

pyinstaller -F -i tubiao\123.ico F:\test\modifyXmldata.py

注意

--需要将程序打包在哪里,就在哪里打开cmd(按住shift键 然后右键,在此处打开cmd窗口)

--有些资源文件如图片等,可直接复制到exe所在的目录下,否则会报错找不到

完成后的效果:

pyqt5_实例:修改xml文件中节点值

pyqt5_实例:修改xml文件中节点值