使用openpyxl保存Excel文件时遇OSError: [Errno 9]错误求助
解决合并Excel时的OSError: [Errno 9] Bad file descriptor问题
问题根源分析
- 路径变量被意外覆盖:原代码中
os.walk循环的迭代变量path重写了初始定义的目录路径,导致后续生成的目标文件路径完全错误,无法正常写入。 - 保存语句位置错误:
destination_workbook.save(destination_file)位于函数外部,既破坏了变量作用域,也无法确保在数据写入完成后执行保存操作。 - 文件句柄泄漏:加载源Excel文件后未显式关闭,导致系统文件句柄被占用,引发访问异常。
- 循环索引逻辑冗余易出错:原代码通过索引偏移遍历文件,增加了出错概率。
修正后的完整代码
import os from openpyxl import load_workbook, Workbook def mergeDataFiles(): # 初始根目录,避免被os.walk覆盖 root_path = "C:\\Users\\ethan\\Desktop\\Benzoyl Chloride\\Benzoyl Chloride" origin_files = [] # 遍历目录,仅收集xlsx格式文件并保存完整路径 for dirpath, _, files in os.walk(root_path): for file in files: if file.endswith(".xlsx"): origin_files.append(os.path.join(dirpath, file)) # 定义目标文件路径 destination_file = os.path.join(root_path, "merged_result.xlsx") # 加载或创建目标工作簿 try: dest_wb = load_workbook(destination_file) dest_sheet = dest_wb["Sheet1"] except FileNotFoundError: dest_wb = Workbook() dest_sheet = dest_wb.active dest_sheet.title = "Sheet1" # 遍历源文件,按列写入数据 for col_idx, file_path in enumerate(origin_files, start=1): # 只读模式加载源文件,with语句自动关闭释放句柄 with load_workbook(file_path, read_only=True) as origin_wb: origin_sheet = origin_wb['Data'] # 写入文件名作为列标题 dest_sheet.cell(row=1, column=col_idx).value = os.path.basename(file_path) # 读取源文件第二列前499行数据,写入目标文件对应列 for row_idx, cell_value in enumerate(origin_sheet.iter_rows(min_row=1, max_row=499, min_col=2, max_col=2, values_only=True), start=2): dest_sheet.cell(row=row_idx, column=col_idx).value = cell_value[0] # 保存合并后的文件(确保在函数内部执行) dest_wb.save(destination_file) print("Excel文件合并完成!") if __name__ == "__main__": mergeDataFiles()
关键修改说明
- 路径安全处理:用
root_path存储初始目录,os.walk使用dirpath作为迭代变量,彻底避免路径被覆盖;同时用os.path.join生成完整文件路径,杜绝拼接错误。 - 自动释放文件资源:使用
with语句加载源工作簿,配合read_only=True提升读取效率的同时,自动关闭文件,避免句柄泄漏。 - 容错处理:增加目标文件不存在时的自动创建逻辑,无需提前手动创建空Excel。
- 简化循环逻辑:用
enumerate直接获取列索引和文件路径,去掉冗余的索引偏移,代码更简洁易维护。 - 过滤无效文件:仅处理
.xlsx格式文件,避免加载非Excel文件引发不必要的错误。
内容的提问来源于stack exchange,提问作者TheBooker66 aka Ethan
相关产品推荐
相关产品推荐

