能把文件处理完的 Python 脚本,并不等于可重复执行的办公任务:目录写死、缺少日志、没有处理计数,换台机器或换个文件类型就容易出错。本文以批量复制 PDF 为例,利用 Python 自带模块把输入目录、输出目录、扩展名和覆盖选项都改成命令行参数,并将运行日志 run.log 与复制数量写入指定目录,让脚本每次执行都有迹可循、结果可核验。当参数、日志和验收闭环建立之后,你的脚本是否还能经得起换个目录重新跑一遍的检验?
— 此摘要由AI分析文章内容生成,仅供参考。
如果你已经有一个能处理文件的 Python 脚本,下一步是让它每次都从明确的输入目录读取文件、把结果写入指定目录,并留下运行记录和处理数量。下面用批量复制 PDF 文件作例子,搭好可重复执行的流程;换成 Excel、Word 或 PDF 内容处理时,也可以沿用相同的参数、日志和验收方式。

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 都会记录扫描文件数、成功数、跳过数和失败数。例如,日志会说明有多少文件符合扩展名筛选,以及每个文件是否复制成功。
验收时可以按以下顺序检查:
- 确认“符合扩展名的文件数”与输入目录中预期处理的文件数一致。
- 对照“成功、跳过、失败”数量,确认总数与符合条件的文件数相符。
- 打开输出目录抽查文件,检查文件名、大小和内容是否符合预期。
- 若本次有失败项,查看日志中的文件名和错误原因,再决定是否重试。
“跳过”表示输出目录中已存在同名文件,并且本次没有启用覆盖。若上次运行中断后留下了不完整的目标文件,默认行为也可能将它跳过;确认可以重新生成后,使用 --overwrite 再运行。
5. 常见问题排查
输入目录为空,或没有匹配的文件
脚本会在日志中写出输入目录的文件数和匹配数。检查文件是否放在指定目录的第一层,以及 --ext 是否正确。例如,文件实际是 .xlsx,但参数仍为默认的 .pdf,匹配数就会是零。
提示权限不足
检查当前账号是否有权限读取输入目录、创建输出目录,以及写入 已处理/run.log。如果文件正被其他程序占用,也可能导致复制失败。先关闭占用文件的程序,再检查目录权限并重试。
只有部分文件失败
脚本会继续处理其他文件,不会因为一个文件失败就停止整批任务。查看日志中对应文件的错误信息,处理占用、权限或路径问题后再运行。默认模式会跳过已有同名文件;需要重新生成时,加上 --overwrite。
实际任务是处理 Excel、Word 或 PDF 内容
保留命令行参数、日志记录、计数和异常处理框架,把示例中的 shutil.copy2(source, target) 替换为实际的文件处理逻辑即可。例如,处理 Excel 时可在每个文件处理完成后增加成功计数;遇到单个文件无法读取时记录异常并继续处理其他文件。这样每次运行都能看清输入是什么、处理了多少、哪些失败,而不只是看到脚本“执行完了”。

评论列表 (8条):
加载更多评论 Loading...