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

Python ValueError: 已关闭文件上的I/O操作问题求助

问题修复方案

错误根源

  1. 多余的文件句柄:你手动执行了file = open(filepath, 'r')但未使用或关闭该句柄,和openpyxl的文件操作产生资源冲突,安装Pillow后,openpyxl对文件资源的处理逻辑更严格,这个冲突被触发。
  2. 循环内过早关闭工作簿:for循环里每次保存后就调用wb.close(),第二次循环时工作簿已关闭,后续操作自然触发"已关闭文件的I/O操作"错误。

修改后的完整代码

from tkinter import filedialog, tk, font
from openpyxl import load_workbook
from openpyxl.worksheet.datavalidation import DataValidation
from pathlib import Path
import pyautogui

def openFile():
    filepath = filedialog.askopenfilename(
                                          title="Please select a file",
                                          filetypes = (('Excel files', '*.xlsx'),
                                                      ('Excel macro files', '*.xlsm'))
                                          )
    # 移除多余的手动文件打开语句,openpyxl会自行处理文件资源
    wb = load_workbook(filepath, read_only=False, keep_vba=True)
    ws=wb.active
    fileonly = filepath.split('/')[-1]
    filewithoutextension = fileonly.split('-')[0]
    fileextension = fileonly.split('.')[-1]

    y = pyautogui.prompt(text='Please specify the number of file duplicates', title='Number of files', default='2')
    if not y:  # 处理用户取消输入的情况
        return
    try:
        y_int = int(y)
        if y_int < 2:
            pyautogui.alert("Please enter a number greater than or equal to 2")
            return
    except ValueError:
        pyautogui.alert("Please enter a valid integer")
        return

    file_path = filedialog.askdirectory()
    if not file_path:  # 处理用户取消选择目录的情况
        return

    # 所有复制任务完成后再关闭工作簿,避免循环内提前关闭导致后续操作失败
    for x in range(2, y_int + 1):
         newname = "%03d" % x
         dv = DataValidation(type="list", formula1='"COLLECTION,INTER PROJECT COLLECTION,INTER PROJECT TRANSFER,TRANSFER"', allow_blank=False)
         dv.error = 'Please select entry from the list!'
         c1 = ws["D4"]
         c1.value = "COLLECTION"
         dv.add(c1)
         ws.add_data_validation(dv)
         save_path = Path(file_path) / f"{filewithoutextension}- {newname}.{fileextension}"
         wb.save(save_path)
         print(f"{filewithoutextension}- {newname}.{fileextension}")
    wb.close()


rootwindow = tk.Tk()
rootwindow.geometry("500x100")
rootwindow.title("Excel file duplicator")
font.families()
windowfont=tk.font.nametofont("TkDefaultFont")
windowfont.config(
    family="Segoe Script",
    size=24,
    weight=font.BOLD)

button = tk.Button(rootwindow, text='Open Excel document',command=openFile, fg='black', bg='yellow')
button.pack()
rootwindow.mainloop()

关键修改点

  • 移除多余的文件打开语句:删掉file = open(filepath, 'r'),openpyxl的load_workbook会自行负责文件的打开和资源释放,手动打开的句柄会干扰其正常操作。
  • 调整工作簿关闭时机:将wb.close()从循环内移到循环外,确保所有复制任务完成后再关闭工作簿,避免后续循环操作已关闭的资源。
  • 增加输入校验:处理用户输入非数字、取消输入或输入小于2的情况,避免程序因非法输入崩溃。

内容的提问来源于stack exchange,提问作者Geographos

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.24 14:04:54