AI Skills(智能体技能)

从 Python 脚本到可重复执行的办公任务:配置输入目录、参数和结果检查

AI智能摘要

能把文件处理完的 Python 脚本,并不等于可重复执行的办公任务:目录写死、缺少日志、没有处理计数,换台机器或换个文件类型就容易出错。本文以批量复制 PDF 为例,利用 Python 自带模块把输入目录、输出目录、扩展名和覆盖选项都改成命令行参数,并将运行日志 run.log 与复制数量写入指定目录,让脚本每次执行都有迹可循、结果可核验。当参数、日志和验收闭环建立之后,你的脚本是否还能经得起换个目录重新跑一遍的检验?

— 此摘要由AI分析文章内容生成,仅供参考。

如果你已经有一个能处理文件的 Python 脚本,下一步是让它每次都从明确的输入目录读取文件、把结果写入指定目录,并留下运行记录和处理数量。下面用批量复制 PDF 文件作例子,搭好可重复执行的流程;换成 Excel、Word 或 PDF 内容处理时,也可以沿用相同的参数、日志和验收方式。

Python 办公脚本从输入文件夹处理文件、生成结果并记录日志的流程示意

1. 准备运行环境和目录

示例只使用 Python 自带模块,不需要额外安装第三方库。先在终端检查 Python 是否可用:

纯文本
python --version

Windows 上如果 python 命令不可用,可以试试:

纯文本
py --version

在脚本所在位置创建以下目录:

纯文本
office_task/
├── batch_copy.py
├── 待处理/
└── 已处理/

把要处理的 PDF 放进“待处理”目录。脚本默认把结果写到“已处理”,运行日志也保存在该目录中。

2. 为脚本添加输入参数、日志和计数

将下面代码保存为 batch_copy.py:

纯文本
from pathlib import Path
import argparse
import logging
import shutil
import sys


def parse_args():
    base_dir = Path(__file__).resolve().parent

    parser = argparse.ArgumentParser(
        description="将指定目录中的文件复制到结果目录,并记录处理情况。"
    )
    parser.add_argument(
        "--input",
        type=Path,
        default=base_dir / "待处理",
        help="输入目录,默认是脚本旁的“待处理”目录",
    )
    parser.add_argument(
        "--output",
        type=Path,
        default=base_dir / "已处理",
        help="输出目录,默认是脚本旁的“已处理”目录",
    )
    parser.add_argument(
        "--ext",
        default=".pdf",
        help="要处理的文件扩展名,例如 .pdf、.xlsx;默认是 .pdf",
    )
    parser.add_argument(
        "--overwrite",
        action="store_true",
        help="覆盖输出目录中已有的同名文件",
    )
    return parser.parse_args()


def setup_logger(output_dir: Path):
    log_path = output_dir / "run.log"

    logger = logging.getLogger("batch_copy")
    logger.setLevel(logging.INFO)
    logger.handlers.clear()

    formatter = logging.Formatter(
        "%(asctime)s %(levelname)s %(message)s"
    )

    file_handler = logging.FileHandler(log_path, encoding="utf-8")
    file_handler.setFormatter(formatter)

    console_handler = logging.StreamHandler()
    console_handler.setFormatter(formatter)

    logger.addHandler(file_handler)
    logger.addHandler(console_handler)
    return logger


def main():
    args = parse_args()
    input_dir = args.input.expanduser().resolve()
    output_dir = args.output.expanduser().resolve()

    if not input_dir.is_dir():
        print(f"输入目录不存在或不是文件夹:{input_dir}", file=sys.stderr)
        return 2

    if input_dir == output_dir:
        print("输入目录和输出目录不能相同。", file=sys.stderr)
        return 2

    extension = args.ext.strip()
    if not extension.startswith("."):
        extension = "." + extension
    extension = extension.lower()

    try:
        output_dir.mkdir(parents=True, exist_ok=True)
        logger = setup_logger(output_dir)
    except OSError as error:
        print(f"无法创建输出目录或运行日志:{error}", file=sys.stderr)
        return 2

    try:
        files = sorted(path for path in input_dir.iterdir() if path.is_file())
    except OSError as error:
        logger.exception("无法读取输入目录:%s", error)
        return 2

    selected = [
        path for path in files
        if path.suffix.lower() == extension
    ]

    copied = 0
    skipped = 0
    failed = 0

    logger.info(
        "开始运行:输入目录文件 %d 个,符合扩展名 %s 的文件 %d 个",
        len(files),
        extension,
        len(selected),
    )

    if not selected:
        logger.warning("没有找到符合条件的文件;请检查输入目录和扩展名。")

    for source in selected:
        target = output_dir / source.name

        if target.exists() and not args.overwrite:
            skipped += 1
            logger.warning("跳过已有文件:%s", target.name)
            continue

        try:
            shutil.copy2(source, target)
            copied += 1
            logger.info("已复制:%s", source.name)
        except OSError:
            failed += 1
            logger.exception("处理失败:%s", source.name)

    logger.info(
        "运行结束:符合条件 %d 个,成功 %d 个,跳过 %d 个,失败 %d 个",
        len(selected),
        copied,
        skipped,
        failed,
    )
    logger.info("运行日志:%s", output_dir / "run.log")

    return 1 if failed else 0


if __name__ == "__main__":
    raise SystemExit(main())

这段脚本默认只扫描输入目录的第一层,不会递归查找子文件夹。--input 和 --output 用来替换目录,--ext 用来指定扩展名;扩展名匹配不区分大小写。默认不覆盖结果目录中的同名文件,只有加上 --overwrite 才会覆盖。

3. 运行脚本并替换参数

在 office_task 目录打开终端,按默认目录和 .pdf 扩展名运行:

纯文本
python batch_copy.py

也可以明确指定目录和扩展名:

纯文本
python batch_copy.py --input "./待处理" --output "./已处理" --ext .pdf

路径包含空格时,用引号括起来。Windows 示例:

纯文本
py batch_copy.py --input "D:工作资料待处理" --output "D:工作资料已处理" --ext .pdf

若要用 Excel 文件测试,可以把扩展名改为 .xlsx:

纯文本
python batch_copy.py --ext .xlsx

如果希望重新处理并覆盖已存在的同名结果:

纯文本
python batch_copy.py --overwrite

默认路径相对于脚本文件所在目录,而不是终端当前所在目录。这样即使从别的位置运行,只要未指定参数,脚本仍会使用脚本旁的“待处理”和“已处理”目录。

4. 保存日志并验收结果

每次运行后,终端和 已处理/run.log 都会记录扫描文件数、成功数、跳过数和失败数。例如,日志会说明有多少文件符合扩展名筛选,以及每个文件是否复制成功。

验收时可以按以下顺序检查:

  1. 确认“符合扩展名的文件数”与输入目录中预期处理的文件数一致。
  2. 对照“成功、跳过、失败”数量,确认总数与符合条件的文件数相符。
  3. 打开输出目录抽查文件,检查文件名、大小和内容是否符合预期。
  4. 若本次有失败项,查看日志中的文件名和错误原因,再决定是否重试。

“跳过”表示输出目录中已存在同名文件,并且本次没有启用覆盖。若上次运行中断后留下了不完整的目标文件,默认行为也可能将它跳过;确认可以重新生成后,使用 --overwrite 再运行。

5. 常见问题排查

输入目录为空,或没有匹配的文件

脚本会在日志中写出输入目录的文件数和匹配数。检查文件是否放在指定目录的第一层,以及 --ext 是否正确。例如,文件实际是 .xlsx,但参数仍为默认的 .pdf,匹配数就会是零。

提示权限不足

检查当前账号是否有权限读取输入目录、创建输出目录,以及写入 已处理/run.log。如果文件正被其他程序占用,也可能导致复制失败。先关闭占用文件的程序,再检查目录权限并重试。

只有部分文件失败

脚本会继续处理其他文件,不会因为一个文件失败就停止整批任务。查看日志中对应文件的错误信息,处理占用、权限或路径问题后再运行。默认模式会跳过已有同名文件;需要重新生成时,加上 --overwrite。

实际任务是处理 Excel、Word 或 PDF 内容

保留命令行参数、日志记录、计数和异常处理框架,把示例中的 shutil.copy2(source, target) 替换为实际的文件处理逻辑即可。例如,处理 Excel 时可在每个文件处理完成后增加成功计数;遇到单个文件无法读取时记录异常并继续处理其他文件。这样每次运行都能看清输入是什么、处理了多少、哪些失败,而不只是看到脚本“执行完了”。

热门话题

52okp 是一名关注人工智能、开源软件与效率工具的技术内容创作者,长期实践 Stable Diffusion、ComfyUI、AI 智能体、MCP、Codex 和各类开源项目。通过实际安装、配置与测试,整理可复现的操作教程、问题排查方法和工具使用经验。

登录用户才能发表评论! 登录账户

取消回复

评论列表 (8条):

加载更多评论 Loading...

延伸阅读:

用 Python 按模板生成办公报告:从 Excel 数据到 Word 文档的自动填充

每周把 Excel 项目进度、负责人和日期重复填进 Word 周报,既费时也容易漏项;Python 可以按模板批量生成文...

52okp
2026-09-26

用 Python 批量处理 PDF 文件:提取文本、按规则命名并检查异常文件

面对合同、发票和资料 PDF,逐个打开、改名、分拣既耗时又容易漏掉异常。借助 Python 与开源 pypdf,可批量提...

52okp
2026-09-24

用 PowerRename 批量重命名照片:替换文本、添加序号并先预览结果

照片批量重命名时,手动逐个修改不仅耗时,还容易出错。PowerRename 作为 PowerToys 中的免费工具,允许...

52okp
2026-09-30

给批量文件脚本加入预览和日志:建立可检查的办公自动化流程

批量整理文件最怕的不是步骤繁琐,而是误操作后难以追查去向。文章以按扩展名归类为例,介绍如何让 Python 脚本默认只预...

52okp
2026-09-27

批量整理文件夹前如何设计分类规则:用项目、类型和日期减少重复劳动

批量整理文件夹常半途翻车,根因不是工具不会移动文件,而是“按项目归档”这类要求没有定义清楚,日期含义、同名冲突、异常去向...

52okp
2026-09-28
    返回顶部