如何用tkinter AskOpenFiles批量打开文件?解决ValueError报错
解决tkinter批量打开文件后pandas读取报错的问题
报错原因
fd.askopenfiles()返回的是多个文件对象组成的列表,但pd.read_csv()仅支持单个文件路径、文件对象或可读取流,直接传入列表就会触发ValueError: Invalid file path or buffer object type: <class 'list'>。
修复步骤及代码修改
1. 调整文件选择与数据加载逻辑
修改Button_frame中的select_file方法,遍历选中的文件逐个读取并合并数据:
def select_file(self): filetypes = ( ("textfiles", ".txt"), ) files = fd.askopenfiles( filetypes=filetypes, mode="r", # 只读模式即可,无需r+ title="Open files", initialdir="/", ) if files: # 遍历读取所有选中文件并合并 dfs = [] for file in files: df = pd.read_csv(file, sep=";", skiprows=[0], low_memory=False) dfs.append(df) file.close() # 读取后关闭文件 merged_data = pd.concat(dfs, ignore_index=True) # 找到Analysis_frame实例并调用分析方法 for child in self.master.winfo_children(): if isinstance(child, Analysis_frame): child.analysis(merged_data) break messagebox.showinfo("Data", "数据加载成功!") else: messagebox.showinfo("Data", "未加载任何数据!")
2. 修改Analysis_frame的analysis方法
不再依赖全局变量data_raw,改为接收合并后的DataFrame作为参数:
def analysis(self, merged_data): global Test_Start, Test_End, Duration, Duration_End, Temperature, MinTemp, MaxTemp, Start_Time, End_Time global Current_IN_max, Current_IN_min, MaxValue_I_IN_max, MinValue_I_IN_max global data data = merged_data Test_Start = data.iloc[:, 0].values[0] Test_End = data.iloc[:, 0].values[-1] Start_Time = data.iloc[:, 1].values[0] End_Time = data.iloc[:, 1].values[-1] Duration = data.iloc[:, 3] Duration_End = data.iloc[:, 3].values[-1] Temperature = data.iloc[:, 4] MinTemp = Temperature.min() MaxTemp = Temperature.max() Humidity = data.iloc[:, 5] Supply_IN_max = data.iloc[:, 8] Supply_IN_min = data.iloc[:, 9] Current_IN_max = data.iloc[:, 12] Current_IN_min = data.iloc[:, 13] Voltage_OUT_max = data.iloc[:, 20] pd.set_option("display.max_rows", 20000)
3. 修复绘图方法的字符串拼接错误
原代码中引号冲突,修改为:
plt.figtext(0.05,0.10,f"Test start: {Test_Start} {Start_Time}", fontfamily="verdana", fontsize=10) plt.figtext(0.85,0.10, f"Test end: {Test_End} {End_Time}", fontfamily="verdana", fontsize=10)
4. 可选优化:减少全局变量使用
建议将全局变量替换为Analysis_frame的类成员变量,避免全局变量污染:
class Analysis_frame(tk.LabelFrame): def __init__(self, container): super().__init__(container) self.configure(text="Analysis", relief="ridge", font=("Verdana", 10), borderwidth=1, border=3) # 初始化类成员变量 self.data = None self.Test_Start = None self.Test_End = None self.Start_Time = None self.End_Time = None self.Duration = None self.Duration_End = None self.Temperature = None self.MinTemp = None self.MaxTemp = None self.Current_IN_max = None self.Current_IN_min = None self.__create_widgets() def analysis(self, merged_data): self.data = merged_data self.Test_Start = self.data.iloc[:, 0].values[0] self.Test_End = self.data.iloc[:, 0].values[-1] self.Start_Time = self.data.iloc[:, 1].values[0] self.End_Time = self.data.iloc[:, 1].values[-1] self.Duration = self.data.iloc[:, 3] self.Duration_End = self.data.iloc[:, 3].values[-1] self.Temperature = self.data.iloc[:, 4] self.MinTemp = self.Temperature.min() self.MaxTemp = self.Temperature.max() self.Current_IN_max = self.data.iloc[:, 12] self.Current_IN_min = self.data.iloc[:, 13] pd.set_option("display.max_rows", 20000) def __create_plot_temp(self): fig, ax1 = plt.subplots(facecolor="white", figsize=(17,10), dpi=100) ax1.set_title("Temperature diagram", font="Verdana", fontsize=11) ax1.set_facecolor("whitesmoke") plt.subplots_adjust(left=0.05, right=0.95, top=0.98, bottom=0.15) ax1.set_ylim(bottom=0, top=1) ax1.set_xlim(0,self.Duration_End) ax2 = ax1.twinx() ax2.set_ylim(bottom=self.MinTemp-10, top=self.MaxTemp+15) ax1.minorticks_on() plt.minorticks_on() ax1.set_ylabel("Current [A]").set_fontsize(10) ax2.set_ylabel("Temperature [°C]").set_fontsize(10) ax1.set_xlabel("Test duration [h]").set_fontsize(10) sample1, = ax1.plot(self.Duration, self.Current_IN_max, label="IGSS1", color="green", marker=".", markersize=2, mouseover=True, linewidth=0.2, visible=True, alpha=0.5) sample2, = ax1.plot(self.Duration, self.Current_IN_min, label="IGSS2", color="orange", marker=".", markersize=2, mouseover=True, linewidth=0.2, visible=True, alpha=0.5) temp, = ax2.plot(self.Duration, self.Temperature, label="Temperature", color="red", linewidth=0.8, alpha=0.7) plt.figtext(0.05,0.10,f"Test start: {self.Test_Start} {self.Start_Time}", fontfamily="verdana", fontsize=10) plt.figtext(0.85,0.10, f"Test end: {self.Test_End} {self.End_Time}", fontfamily="verdana", fontsize=10) plt.show()
关键说明
- 使用
pd.concat()合并数据的前提是所有选中文件的列结构完全一致;如果结构不同,需要先处理列对齐逻辑。 - 读取文件后务必关闭,或者用
with语句自动管理文件生命周期:with file as f: df = pd.read_csv(f, ...)。
内容的提问来源于stack exchange,提问作者Michal
相关产品推荐
相关产品推荐

