You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.26 12:44:55