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

Python批量重命名Excel文件时遭遇[Errno 2]文件未找到及AttributeError问题排查

问题排查与修复方案

首先,咱们来拆解你遇到的两个核心问题,以及代码里的其他潜在Bug:

1. AttributeError: 'str' object has no attribute 'is_file' 的根源

os.listdir() 返回的是指定路径下文件名的字符串列表,不是 pathlib.Path 对象。所以当你尝试调用 files.is_file() 或者 file.is_file() 时,本质是在对字符串调用只有Path对象才有的方法,自然会报错。

2. 代码里的其他关键问题

  • extract_date 函数逻辑错误:函数内部循环遍历所有文件,然后直接 return ws['C5'].value,这意味着它只会返回第一个Excel文件的C5值,而不是每个文件自己的C5内容,完全不符合批量重命名的需求。
  • 变量名冲突与循环逻辑混乱:比如在 user_choice == 'y' 的分支里,for file in os.path.join(SPEC_PATH, file): 这行存在两个问题:一是变量名 file 重复使用,二是 os.path.join 返回的是字符串,遍历字符串会逐个字符迭代,这完全不是你想要的遍历文件的逻辑。
  • 重命名逻辑错误:你尝试用 file.rename(),但如果 file 是字符串的话,根本没有这个方法;而且新文件名的拼接也有问题,比如 new_name = f"{head_string}{file.suffix}" 没有用到从C5提取的内容,和需求不符。
  • 路径处理不一致:混合使用 os 模块和 pathlib 模块的路径处理方式,容易导致路径格式混乱,建议统一用 pathlib 来处理所有路径操作,更简洁可靠。

修复后的完整代码

下面是修正了所有问题的代码,完全符合你的需求:

import pathlib
import re
from openpyxl import load_workbook

# 获取用户输入路径并转为绝对路径
spec_path = pathlib.Path(input("请输入文件路径: ")).resolve()

def format_name(raw_name):
    # 清理文件名中不合法的字符
    return re.sub(r"[^\w\-_. ]", "", str(raw_name))

def extract_cell_value(file_path, cell="C5"):
    # 提取指定Excel文件中指定单元格的值
    try:
        wb = load_workbook(file_path, read_only=True)
        ws = wb.active
        cell_value = ws[cell].value
        wb.close()
        # 确保提取的值不为空,否则返回默认标识
        return str(cell_value) if cell_value is not None else f"未识别内容_{file_path.stem}"
    except Exception as e:
        print(f"读取文件 {file_path.name} 失败: {e}")
        return f"读取失败_{file_path.stem}"

# 主逻辑
user_choice = input("是否需要在新文件名前添加前缀字符串?(y/n) ").strip().lower()

# 统一获取路径下所有Excel文件
excel_files = [f for f in spec_path.iterdir() if f.suffix in (".xls", ".xlsx") and f.is_file()]

if not excel_files:
    print("指定路径下没有找到Excel文件!")
else:
    prefix = ""
    if user_choice == 'y':
        prefix = input("请输入前缀字符串: ").strip()
        # 清理前缀中的非法字符
        prefix = format_name(prefix)
    
    success_count = 0
    for file in excel_files:
        # 提取当前文件的C5单元格内容
        cell_content = extract_cell_value(file)
        # 格式化单元格内容作为文件名主体
        formatted_name = format_name(cell_content)
        # 拼接新文件名
        if prefix:
            new_file_name = f"{prefix}_{formatted_name}{file.suffix}"
        else:
            new_file_name = f"{formatted_name}{file.suffix}"
        
        # 构造新的文件路径
        new_file_path = spec_path / new_file_name
        
        # 避免重名覆盖,若已存在则添加数字后缀
        counter = 1
        while new_file_path.exists():
            new_file_name = f"{formatted_name}_{counter}{file.suffix}" if not prefix else f"{prefix}_{formatted_name}_{counter}{file.suffix}"
            new_file_path = spec_path / new_file_name
            counter += 1
        
        try:
            file.rename(new_file_path)
            print(f"成功重命名: {file.name} -> {new_file_name}")
            success_count += 1
        except OSError as e:
            print(f"重命名 {file.name} 失败: {e}")
    
    print(f"\n批量重命名完成,成功处理 {success_count}/{len(excel_files)} 个文件")

修复说明

  1. 统一使用 pathlib:所有路径操作都用 pathlib.Path 对象,彻底避免字符串路径的各种问题,is_file()、rename() 等方法都能正常调用。
  2. 修正 extract_cell_value 函数:改为接收单个文件路径作为参数,返回该文件的指定单元格内容,确保每个文件都能获取自己的C5值。
  3. 添加文件名合法性处理:用正则清理文件名中的非法字符,避免重命名时因字符不合法报错。
  4. 重名处理逻辑:如果新文件名已存在,自动添加数字后缀,防止文件被覆盖。
  5. 错误捕获与提示:增加了文件读取和重命名的错误捕获,方便排查单个文件的问题。
  6. 清晰的流程逻辑:先获取所有Excel文件,再根据用户选择处理前缀,最后逐个重命名,逻辑更清晰易懂。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.28 17:32:47