CSV 文件修改工具开发过程
本文档记录了 CSV 文件修改工具的开发过程,包括逐步优化的过程和最终打包为 Windows 可执行文件的步骤。
初始版本
功能需求
- 带 UI 界面,有 3 个输入框,分别是年 (2021-2024)、月 (01-12)、日 (01-31)。
- 文件选择按钮,点击后可选择要输入的文件,支持多个文件同时选择。
提供一个按钮,按文件列表开始逐个文件进行修改,并保存到源文件,按以下规则修改:
- 修改 A 列时间:如果 A 列第一行是 "WRITE_TIME",则执行步骤②检查、修改 A 列从第二行开始的表格。
- 检查格式是否为时间格式 “[2023-05-17 11:06:55.865]”,如果是,执行步骤③。
- 修改该行单元格内容为输入框的年、月、日,后面的时分秒时间保持不变。
- 如果①、或者②不满足条件,弹窗提示错误,并略过这个文件继续执行下个文件。
- 修改完成保存,并将文件的创建日期修改为 A2 单元格内的时间,修改日期修改为 A 列最后一行内容单元格内的时间。
- 提供一个日志框,输出修改日志。
初始代码
import tkinter as tk
from tkinter import filedialog, messagebox
import pandas as pd
from datetime import datetime
import os
import threading
def modify_files():
year = year_entry.get()
month = month_entry.get()
day = day_entry.get()
if not (year.isdigit() and month.isdigit() and day.isdigit()):
messagebox.showerror("输入错误", "年、月、日必须是数字")
return
year = int(year)
month = int(month)
day = int(day)
if not (2021 <= year <= 2024 and 1 <= month <= 12 and 1 <= day <= 31):
messagebox.showerror("输入错误", "年、月、日值不在有效范围内")
return
files = filedialog.askopenfilenames(filetypes=[("CSV files", "*.csv")])
if not files:
messagebox.showwarning("未选择文件", "请选择至少一个文件")
return
thread = threading.Thread(target=process_files, args=(files, year, month, day))
thread.start()
def process_files(files, year, month, day):
for file in files:
try:
df = pd.read_csv(file)
if df.columns[0] != "WRITE_TIME":
raise ValueError("第一行不是 'WRITE_TIME'")
modified = False
for i in range(1, len(df)):
timestamp = df.iloc[i, 0]
if isinstance(timestamp, str) and timestamp.startswith("[") and timestamp.endswith("]"):
try:
datetime_obj = datetime.strptime(timestamp, "[%Y-%m-%d %H:%M:%S.%f]")
new_timestamp = f"[{year}-{month:02d}-{day:02d} {datetime_obj.strftime('%H:%M:%S.%f')[:-3]}]"
df.iloc[i, 0] = new_timestamp
modified = True
except ValueError:
raise ValueError(f"文件 {file} 中第 {i+1} 行格式不正确")
else:
raise ValueError(f"文件 {file} 中第 {i+1} 行格式不正确")
if modified:
df.to_csv(file, index=False)
file_creation_time = datetime.strptime(df.iloc[0, 0], "[%Y-%m-%d %H:%M:%S.%f]")
file_modification_time = datetime.strptime(df.iloc[-1, 0], "[%Y-%m-%d %H:%M:%S.%f]")
os.utime(file, (file_modification_time.timestamp(), file_creation_time.timestamp()))
log_text.insert(tk.END, f"文件 {file} 修改成功
")
else:
log_text.insert(tk.END, f"文件 {file} 无需修改
")
except Exception as e:
log_text.insert(tk.END, f"文件 {file} 修改失败: {e}
")
root = tk.Tk()
root.title("CSV 文件修改工具")
tk.Label(root, text="年 (2021-2024):").grid(row=0, column=0, padx=5, pady=5)
year_entry = tk.Entry(root)
year_entry.grid(row=0, column=1, padx=5, pady=5)
tk.Label(root, text="月 (01-12):").grid(row=1, column=0, padx=5, pady=5)
month_entry = tk.Entry(root)
month_entry.grid(row=1, column=1, padx=5, pady=5)
tk.Label(root, text="日 (01-31):").grid(row=2, column=0, padx=5, pady=5)
day_entry = tk.Entry(root)
day_entry.grid(row=2, column=1, padx=5, pady=5)
tk.Button(root, text="选择文件并修改", command=modify_files).grid(row=3, column=0, columnspan=2, padx=5, pady=5)
log_text = tk.Text(root, height=10, width=50)
log_text.grid(row=4, column=0, columnspan=2, padx=5, pady=5)
root.mainloop()
第一轮优化
添加进度条和日志改进
为了改进用户体验,增加进度条显示处理进度,同时增加日志文件的存储,每个处理步骤均在界面上的日志框和日志文件中记录。
第二轮优化
性能优化
对于大文件的处理,采用 pandas
的向量化处理方法优化数据处理速度,同时使用内存映射技术减少内存消耗。
打包为 Windows 可执行文件
使用 PyInstaller
将 Python 脚本打包为 Windows 可执行文件,方便用户在没有 Python 环境的情况下运行程序。
打包命令
pyinstaller --onefile --windowed --name CSVModifier your_script.py
日志文件改进
日志文件名现在包含日期时间,确保每次运行的日志不会相互覆盖,方便历史数据查询。