Python : 批量自动替换代码文件内容,批量移动/覆盖代码文件
使用背景
批量代码文件内容修改,可用在生成代码工具上。
例如在设备端GUI页面显示上,很多是通过GUI上位机软件自动生成代码,然后把生成的代码copy到开发工程中编译使用。
但由于种种原因,存在生成的代码与实际工程有些不兼容的情况,则生成的代码不能直接copy使用。。
我之前遇到的是每次都需要改动一部分代码及文件名,才能放到工程正确编译,而GUI上位机是官方提供的无法修改。。。这就导致每次改UI 生成的所有代码就得做一次修改,手动做太麻烦,所以通过一个工具自动化实现上面步骤。
工具主要功能:检索并替换目录中所有的.c/.cpp, .h/.hpp文件及相关内容,之后自动copy并覆盖到指定目录。
实际应用中 比如中有个头文件 或变量名改动了:则通过工具一键替换,非常方便且高效,因为会检索目录中所有文件的全部内容
先上图:
代码解析 - getCppHppFileList
getCppHppFileList 是通过os 的api 把目录的所有文件名作为 list return,既获取目录中所有的 代码文件
def getCppHppFileList(code_path):
_files = {}
list = os.listdir(code_path)
for i in range(0, len(list)):
path = os.path.join(code_path, list[i])
if os.path.isfile(path):
(filepath, tempfilename) = os.path.split(path)
(filename, extension) = os.path.splitext(tempfilename)
if extension == '.cpp' or extension == '.c' or extension == '.hpp' or extension == '.h':
_files[list[i]] = tempfilename
return _files
代码解析 - replace_StrInFile
replace_StrInFile 就是遍历文件内容,找到要替换的str 并且执行替换操作,使用了with 更加安全的操作文件。
def replace_StrInFile(file, Old, New):
file_data =""
isconfigLine = 0
with open(file, "r") as f:
for line in f:
if Old in line:
isconfigLine = 1
line = "#include \""+New+"\"\n"
print("replaced "+New+" in file: "+file)
file_data += line
with open(file, "w") as f:
f.write(file_data)
这里只是替换了头文件名(因为我实际的代码是头文件名要改)
如果替换任意字符,使用下面方法,,而且上面方法是遍历改完后整个文件write,下面方法使用writelines效率会好一些:
def replace_StrinFile(FileName, OldStr, NewStr):
file = open(FileName, 'r')
alllines = file.readlines()
file.close()
file = open(FileName, 'w+')
for eachline in alllines:
a = re.sub(OldStr, NewStr, eachline)
file.writelines(a)
file.close()
代码解析 - reName_File
reName_File 直接使用shutil.copyfile(src, dst), 而移动并覆盖文件用的shutil.copy(src, dst)
def reName_File(srcFile, dstFile):
try:
shutil.copyfile(srcFile, dstFile)
except IOError as e:
print("Unable to backup file. %s" % e)
exit(1)
except:
print("Unexpected error:", sys.exc_info())
exit(1)
else:
print("reName file: "+dstFile+" success!\r")
代码解析 -Tkinter 图形界面
界面很简单,就是一个Text框和一个Button用来选择目标文件目录
这个UI代码结构也是我之前其他工具沿用的。。
def selectBtn():
filename = tkinter.filedialog.askdirectory()
if filename != '':
intro.config(text =filename);
moveCodeFilesToDstFolder(filename)
btn.config(text = "替换完成, 自动关闭窗口")
root.destroy()
else:
intro.config(text = "没有选择任何文件夹");
root = Tk()
root.geometry('600x300')
root.title('AutoReplace2.0')
root.config(bg='#f0ffff')
intro = Label(root, text='点击按钮选择要Copy覆盖的目录', \
bg='#f0ffff', \
fg='black', \
font=('华文新魏', 10), \
width=50, \
height=5)
intro.place(relx=0.1, rely=0.1, relwidth=0.8, relheight=0.3)
btn = Button(root, text="选择待替换目录,完成自动关闭窗口", command=selectBtn, \
fg='red', \
font=('华文新魏', 14), \
width=20, \
height=5)
btn.place(relx=0.1, rely=0.5, relwidth=0.8, relheight=0.2)
root.mainloop()
完整代码
#/usr/bin/python
#coding:utf-8
"""
To replace all include file name of embedded wizard generated code
"""
__author__ = 'HowardXue 2020.06.10'
import fileinput
import os
import time
import shutil
from tkinter import *
import tkinter.filedialog
#import re
#import io
core_str = """Core.h"""
guiCore_str = """GUI_Core.h"""
res_str = """Resources.h"""
guiRes_str = """GUI_Resources.h"""
SrcfilePath = "./GeneratedCode"
def getCppFileList(code_path):
_files = {}
list = os.listdir(code_path)
for i in range(0,len(list)):
path = os.path.join(code_path,list[i])
if os.path.isfile(path):
(filepath,tempfilename) = os.path.split(path)
(filename,extension) = os.path.splitext(tempfilename)
if extension == '.c' or extension == '.cpp':
_files[list[i]] = tempfilename
return _files
def getCppHppFileList(code_path):
_files = {}
list = os.listdir(code_path)
for i in range(0, len(list)):
path = os.path.join(code_path, list[i])
if os.path.isfile(path):
(filepath, tempfilename) = os.path.split(path)
(filename, extension) = os.path.splitext(tempfilename)
if extension == '.cpp' or extension == '.c' or extension == '.hpp' or extension == '.h':
_files[list[i]] = tempfilename
return _files
def replace_StrInFile(file, Old, New):
file_data =""
isconfigLine = 0
with open(file, "r") as f:
for line in f:
if Old in line:
isconfigLine = 1
line = "#include \""+New+"\"\n"
print("replaced "+New+" in file: "+file)
file_data += line
with open(file, "w") as f:
f.write(file_data)
def reName_File(srcFile, dstFile):
try:
shutil.copyfile(srcFile, dstFile)
except IOError as e:
print("Unable to backup file. %s" % e)
exit(1)
except:
print("Unexpected error:", sys.exc_info())
exit(1)
else:
print("reName file: "+dstFile+" success!\r")
def autoReplaceNameFile():
os.chdir(SrcfilePath)
cFilelist = getCppFileList(os.getcwd())
for file in cFilelist.values():
# print(file)
replace_StrInFile(file, core_str, guiCore_str)
replace_StrInFile(file, res_str, guiRes_str)
reName_File("Core.c", "GUI_Core.c")
reName_File("Core.h", "GUI_Core.h")
reName_File("Resources.c", "GUI_Resources.c")
reName_File("Resources.h", "GUI_Resources.h")
os.chdir("../")
print("\n AutoReplaceName Finished...")
def moveCodeFilesToDstFolder(DstfilePath):
os.chdir(SrcfilePath)
#print(DstfilePath)
cFilelist = getCppHppFileList(os.getcwd())
for file in cFilelist.values():
#print(file)
shutil.copy(file, DstfilePath)
os.chdir("../")
print("\nMove all .c/.h file \n from:" + os.getcwd() + "\n to :" + DstfilePath + " Success!")
def selectBtn():
filename = tkinter.filedialog.askdirectory()
if filename != '':
intro.config(text =filename);
moveCodeFilesToDstFolder(filename)
btn.config(text = "替换完成, 自动关闭窗口")
root.destroy()
else:
intro.config(text = "没有选择任何文件夹");
if __name__ == "__main__":
root = Tk()
root.geometry('600x300')
root.title('AutoReplace2.0')
root.config(bg='#f0ffff')
autoReplaceNameFile()
intro = Label(root, text='点击按钮选择要Copy覆盖的目录', \
bg='#f0ffff', \
fg='black', \
font=('华文新魏', 10), \
width=50, \
height=5)
intro.place(relx=0.1, rely=0.1, relwidth=0.8, relheight=0.3)
btn = Button(root, text="选择待替换目录,完成自动关闭窗口", command=selectBtn, \
fg='red', \
font=('华文新魏', 14), \
width=20, \
height=5)
btn.place(relx=0.1, rely=0.5, relwidth=0.8, relheight=0.2)
root.mainloop()
print("\nAll Finished, this window will auto close after 10s...")
time.sleep(10)
博主热门文章推荐:
一篇读懂系列:
LoRa Mesh系列:
网络安全系列:
- ATECC508A芯片开发笔记(一):初识加密芯片
- SHA/HMAC/AES-CBC/CTR 算法执行效率及RAM消耗 测试结果
- 常见加密/签名/哈希算法性能比较 (多平台 AES/DES, DH, ECDSA, RSA等)
- AES加解密效率测试(纯软件AES128/256)–以嵌入式Cortex-M0与M3 平台为例
嵌入式开发系列:
- 嵌入式学习中较好的练手项目和课题整理(附代码资料、学习视频和嵌入式学习规划)
- IAR调试使用技巧汇总:数据断点、CallStack、设置堆栈、查看栈使用和栈深度、Memory、Set Next Statement等
- Linux内核编译配置(Menuconfig)、制作文件系统 详细步骤
- Android底层调用C代码(JNI实现)
- 树莓派到手第一步:上电启动、安装中文字体、虚拟键盘、开启SSH等
- Android/Linux设备有线&无线 双网共存(同时上内、外网)
AI / 机器学习系列:
- AI: 机器学习必须懂的几个术语:Lable、Feature、Model…
- AI:卷积神经网络CNN 解决过拟合的方法 (Overcome Overfitting)
- AI: 什么是机器学习的数据清洗(Data Cleaning)
- AI: 机器学习的模型是如何训练的?(在试错中学习)
- 数据可视化:TensorboardX安装及使用(安装测试+实例演示)
其他好玩的python脚本
Python实现自动发送邮件 --自动抓取博客/网站中留言的邮箱并发送相应邮件
Python自动生成代码 - 通过tkinter图形化操作并生成代码框架
Python解析CSV数据 - 通过Pandas解析逻辑分析仪导出的CSV数据
Python通过Django搭建网站执行Lua脚本 (实现数据解析)