ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Python自动化脚本实战:从环境配置到定时任务全流程

Python自动化脚本实战:从环境配置到定时任务全流程 我最早认真写Python自动化脚本不是为了搞什么“大工程”纯粹是受不了每天下班前那半个小时的重复劳动下载文件夹里躺着各种PDF、图片、压缩包要给它们重新命名、按类型和日期归类还要把最新的报表发给相关的人。起初我用鼠标一个个点后来实在觉得荒唐就花了一个晚上写了第一个整理脚本。严格来说那个脚本写得挺糙但它帮我省下了此后无数个“半小时”。也是从那以后我意识到日常工作的“自动化”这个词听起来高级落到实处其实是一个很朴素的问题哪些事你每天做一遍、规则又很固定那它们就都值得被写成一个脚本替你跑掉。这篇内容想和你完整走一遍“一个Python脚本的诞生”全过程从怎么判断需求、怎么搭环境到写代码、加参数、做测试再到把它挂进定时任务里无人值守地跑。适合两种人看一种是刚开始学Python、写过几行语法但不知道怎么落地成实际工具的另一种是已经会用Python处理小任务但每次都是“手动跑一下”还没把脚本真正变成日常工作里稳定运转的一部分。看完你会发现自动化没有多神秘它拼的不是高超技巧而是你做判断时的克制和写细节时的耐心。1. 需求先行不是所有重复劳动都值得写成脚本1.1 判断一个场景该不该自动化的三个标准写脚本前先回答一个更关键的问题这件事真的适合自动化吗我见过太多人热情高涨地写了个自动填表单脚本结果网站改版一次就废掉也有人辛辛苦苦做了个爬虫跑了三天就被对方封了IP。项目流产的原因往往不是代码不行而是需求本身选错了。我的经验是判断一个日常工作值不值得自动化就套三个标准规则明确。你能用两三句话把它的处理逻辑说清楚没有那么多例外和主观判断。比如“把下载文件夹里超过7天未打开的文件移到归档目录”规则清楚得像说明书而“把重要的邮件挑出来汇总”什么叫“重要”本身就需要定义。频率够高、耗时可观。每天一次和每年一次投入产出完全不同。单次耗时5分钟、每天重复一年下来就是20多个小时如果只是每月一次且5分钟能搞定写一小时脚本就得仔细掂量了。失败影响可控。脚本跑错时最坏会怎样删几个文件还是清空整个数据库如果影响无法接受那就要在设计和测试上多花大力气甚至在前期就放弃自动化。我有个做设备老化测试的朋友他的日常工作就是盯着设备跑测试、记数据、生成报告一盯就是几个小时。我建议他把“全自动执行测试并生成报告”提上日程因为这场景完全命中上述三条规则固定、每天重复、且失败造成的只是数据采样问题风险可控。后来他用Python写了套脚本至少把人从工位上解放了出来。判断清楚了这个自动化才做得值。1.2 别急着写码先把整个流程拆成输入、处理、输出确定要做之后也别打开编辑器就敲import os。我自己的习惯是先在纸上画一条流水线哪怕只是草草几笔。所谓流程无非三段输入是什么处理规则是什么输出要变成什么。以最常见的“整理下载文件夹”来说输入一个真实目录下的文件集合处理规则按扩展名归类到文档、图片、压缩包、安装包按修改时间决定是否归档到当月目录输出移动之后的目录结构还有一份“本次移动了哪些文件”的小结。把需求拆成这三段之后你会立刻看见模糊的地方“文档”具体指哪些扩展名Excel算文档还是数据文件移动时文件名冲突怎么办这些“模糊地带”才是自动化项目里真正的难点而不是代码本身。一次我帮同事做报表合并工具我以为需求就是“合并文件夹里所有Excel”结果他补充了五个“但是”有的表头不在第一行有的需要跳过“合计”行还有的要按部门拆成多个子表。要不是先做了流程拆解直接开写必然返工。所以这一阶段的产出物不是代码而是一段人话版本的说明什么时候跑、跑之前要满足什么条件、跑完之后应该看到什么。这段说明之后会变成你的README、你的注释以及你和将来的自己之间的沟通桥梁。1.3 自动化项目的“从 0 到 1”六步法这些年下来我把一个自动化脚本从想法到稳定的过程总结成六个步骤后面的章节就按这个顺序展开摸清现状把当前手动操作的过程一步步走一遍记录每一步的动作和耗时定义范围写清楚脚本管哪些文件、不管哪些文件最小实现先做一个只能跑一次的版本验证核心逻辑走通加参数和容错把可变的部分参数化把可能报错的地方接住自动化运行用定时任务或触发器让它无人值守地跑监控与复盘日志、通知、隔段时间回看一次规则是否还适用。判断完需求和范围心里那颗“想立刻写码”的心可以先收一收下一章先把环境这件事理顺。环境问题虽然不性感但它恰恰是脚本活不过第一周的头号原因。2. 环境准备与工程习惯别让“跑不起来”毁掉你的热情2.1 Python安装与版本管理选对工具才能少踩坑现在的Python版本分化已经不严重了但我还是建议装3.9以上版本没必要为了兼容老代码而去碰Python 2。Windows用户去官网下载安装包时有一点要注意安装向导第一页那里有个“Add Python to PATH”勾选框默认不勾请务必勾上。这一步对应的就是很多人之后遇到的“python不是内部或外部命令”的全部根源。系统装好Python之后我强烈建议所有自动化项目都用虚拟环境也就是venv。不要把包直接装到全局环境里不然过两个月你就会遇到“上次跑得好好的今天怎么报错”“这个项目要pandas 1.x那个项目要pandas 2.x”这种互踩地雷的尴尬。我自己就吃过这个亏全局环境里装了一堆包某天升级了一个依赖库结果三个老脚本同时报废排查到凌晨才定位是版本冲突。创建项目目录并启用虚拟环境的常规操作是# 创建项目目录 mkdir organize_files cd organize_files # 创建并激活虚拟环境 python -m venv venv # Windows PowerShell 下激活 venv\Scripts\activate # Linux/macOS 下激活 source venv/bin/activate激活后命令行前面会出现(venv)字样之后安装的所有包都只属于这个项目不会污染系统环境也不怕影响别的脚本。这几十秒的投资值。2.2 依赖锁定与项目结构脚本也需要“工程感”即使是简单的自动化脚本我也建议至少保持一个像样的目录结构避免半年后回来看代码一头雾水。下面是我个人惯用的骨架organize_files/ ├── organize.py ├── requirements.txt ├── README.md ├── tests/ │ └── test_organize.py └── venv/requirements.txt 的作用是把项目用到的第三方库连同版本号一起锁住。养成习惯每当环境里成功装了一批包就执行一次pip freeze requirements.txt这样别人拿到代码或者你换台电脑一条命令就能把环境重建出来pip install -r requirements.txt很多新手不建虚拟环境也不锁版本等脚本在别人机器上跑不起来时才病急乱投医。实际上大部分“我明明装了啊为什么import不到”的问题十有八九是把包装进了A环境、运行脚本却用了B环境。你在终端里敲which python看一眼再确认当前激活的是不是项目的venv思路会比瞎装包清晰得多。另外Windows下脚本运行时常见“一闪而过”的问题我也放到这里提醒如果你双击的是 .bat 或 .py 文件窗口秒关不代表脚本没跑而是跑完正常退出。想看输出就打开PowerShell或cmd手动切到项目目录再执行输出会留在终端里。用cmd跑一下cd /d D:\your_project venv\Scripts\python organize.py这样真出异常也能看到完整的报错堆栈不至于两眼一抹黑。2.3 环境变量与PATH类报错一个典型问题引发的思考热搜里那些“pnpm无法被识别”“python不是内部或外部命令”其实都指向同一个底层概念操作系统的PATH环境变量。PATH里记录了系统在哪个目录下找可执行程序装软件时没把安装路径加进PATH或者加了之后没有重新打开终端就会出现“明明装了但命令找不到”的现象。我遇到过同事在PowerShell里装好了一个工具立刻运行却报“无法将 x 项识别为 cmdlet、函数、脚本文件或可运行程序的名称”。我先问他你是不是没开新终端他重开了一个之后问题果然消失。因为命令行的环境变量是在启动时读取的老窗口还保存着旧状态。这些经验放在Python里是完全相通的安装完Python后要新开终端virtualenv切换后要注意当前shell环境pip装完了新包但脚本还是找不到模块时优先怀疑是不是没有在同一个解释器环境下执行。同一个原则也适用于排查各种脚本类工具链问题先确认进程用的是哪个解释器/运行时再讨论版本和依赖这是所有环境类排障的统一套路。3. 第一个脚本的完整诞生以批量文件整理为例3.1 需求实例化给脚本定行为边界理论说了一堆现在落到实打实的代码上。我用“整理下载文件夹”这个最容易上手的场景来走完整流程。先描述需求D:\Downloads实际请换成你自己的目录里有各种散乱文件脚本要按扩展名把它们分到文档、图片、压缩包、安装包等子目录同时按文件的最后修改时间归入对应月份的二级目录里比如文档/2024-05。运行之后屏幕打印出每个文件从哪移到哪以及本次共处理多少文件。这里我先定义几个行为的边界只处理常规文件不处理子目录遇到同名文件不覆盖而是追加时间戳脚本要内置一个“预览模式”只打印计划不实际移动文件。第3条尤其重要。新手写自动化文件操作时最容易犯的错就是直接动手改文件跑完才发现归档规则有误文件已经散布到几十个目录里去了。dry-run 模式相当于给脚本装了个安全阀我强烈建议所有涉及删除、移动、重命名的脚本都做这个设计。3.2 代码实现用pathlib而不是os.pathPython 3.4以后Pathlib成为操作路径的主流方式比起os.path.join、os.listdir的组合Pathlib的可读性好得多而且跨平台。下面的代码可以直接复制保存为organize.pyimport argparse import shutil import sys from datetime import datetime from pathlib import Path CATEGORY_RULES { 文档: [.pdf, .doc, .docx, .txt, .md, .xls, .xlsx, .ppt, .pptx], 图片: [.jpg, .jpeg, .png, .gif, .bmp, .webp, .svg], 压缩包: [.zip, .rar, .7z, .tar, .gz, .bz2], 安装包: [.exe, .msi, .dmg, .pkg, .deb, .rpm], } def get_category(ext: str) - str: ext ext.lower() for category, exts in CATEGORY_RULES.items(): if ext in exts: return category return 其他 def build_target_path(source: Path, target_base: Path, category: str, ext: str) - Path: month_folder source.stat().st_mtime month_str datetime.fromtimestamp(month_folder).strftime(%Y-%m) target_dir target_base / category / month_str target_dir.mkdir(parentsTrue, exist_okTrue) target_file target_dir / source.name if target_file.exists(): stem source.stem suffix source.suffix timestamp datetime.now().strftime(%H%M%S) target_file target_dir / f{stem}_{timestamp}{suffix} return target_file def organize(source_dir: Path, target_dir: Path, dry_run: bool True) - None: if not source_dir.exists(): print(f源目录不存在: {source_dir}) sys.exit(1) moved_count 0 for item in source_dir.iterdir(): if not item.is_file(): continue category get_category(item.suffix) target build_target_path(item, target_dir, category, item.suffix) if dry_run: print(f[预览] {item.name} - {target.relative_to(target_dir)}) else: shutil.move(str(item), str(target)) print(f[移动] {item.name} - {target.relative_to(target_dir)}) moved_count 1 print(f共整理 {moved_count} 个文件。) if __name__ __main__: parser argparse.ArgumentParser(description按类型和日期整理文件夹) parser.add_argument(--source, typePath, defaultPath.home() / Downloads, help要整理的源目录) parser.add_argument(--target, typePath, defaultPath.home() / Downloads_Sorted, help归档目标目录) parser.add_argument(--dry-run, actionstore_true, help只预览不执行) args parser.parse_args() organize(args.source, args.target, args.dry_run)这段代码有四个值得注意的细节第一get_category里先统一转小写避免.PDF和.pdf被当成两种类型第二build_target_path里用source.stat().st_mtime读取文件的最后修改时间再用datetime.fromtimestamp转成年月字符串这样归档目录会自然按时间形成层级第三重名冲突没有选择覆盖而是追加当前时间戳这个策略虽然没有那么“优雅”但在真实文件系统里最保险第四shutil.move参数我都转成了字符串形式为的是避免某些第三方库对 Path 对象兼容性不好的边缘情况。3.3 用dry-run验证逻辑之后才动真格首次运行先别直接移动文件python organize.py --source D:\Downloads --target D:\Downloads_Sorted --dry-run终端会列出所有计划执行的动作。仔细扫一眼输出看看扩展名分类对不对有没有该归档但被归到“其他”的文件有没有规则里没覆盖到的格式。确认没问题之后去掉--dry-run再跑一次python organize.py --source D:\Downloads --target D:\Downloads_Sorted我实际跑的时候发现真实文件夹里“其他”类别增长很快因为各种无扩展名文件、临时文件.tmp、日志文件.log都堆在那里。如果你也遇到这种情况可以在CATEGORY_RULES里继续补充规则比如日志文件属于“日志”临时文件直接放入“临时”。规则是人根据现实迭代出来的脚本也会越长越顺手。这个例子虽然简单但它已经覆盖了Python自动化的骨架路径遍历、规则分类、目标计算、安全预览、参数入口。后面要让它自动运行其实已经水到渠成。4. 从手动到自动让脚本在没人记得它时也在工作4.1 Windows环境下的定时运行三件套脚本本身写好了但如果你每次都手动打开终端执行自动化还只完成了一半。真正的自动化是让脚本自己按点或按事件跑起来。Windows上我常用三种方式从推荐程度排序任务计划程序Task Scheduler图形界面适合不想记命令的人。新建任务时触发器设为“每天”或“计算机启动时”操作选“启动程序”程序填venv\Scripts\python.exe的完整路径参数填organize.py的完整路径“起始于”填项目目录。schtasks 命令适合快速注册。管理员权限的cmd里执行类似下面的命令schtasks /Create /SC DAILY /TN OrganizeDownloads /TR D:\organize_files\venv\Scripts\python.exe D:\organize_files\organize.py --no-dry-run /ST 18:00PowerShell开机自启脚本把 .bat 放进shell:startup文件夹。简单直接但只能等用户登录后才运行。批处理内容我一般这样写echo off cd /d D:\organize_files venv\Scripts\python.exe organize.py --no-dry-run organize.log 21提醒一句用任务计划程序时很多人会默认勾选“不管用户是否登录都要运行”这个时候系统要求你填Windows账号密码而且运行环境是Session 0部分依赖网络驱动器或GUI的程序会异常。如果你的脚本只是处理本地文件选“只在用户登录时运行”其实更稳。4.2 Linux/macOS下的cron与launchd如果你跑脚本的机器是Linux服务器或者公司配的Mac更常见的方案是cron。用crontab -e编辑当前用户的定时任务举例# 每天 18:30 执行整理脚本输出写入日志 30 18 * * * cd /home/user/organize_files /home/user/organize_files/venv/bin/python organize.py --no-dry-run organize.log 21这里面有个常见误区cron执行时环境变量很少PATH几乎为空所以命令里最好用绝对路径。直接写python很容易出现“找不到命令”。还记得前面说的环境变量问题吗这里又是同一个根源。macOS的图形化场景用launchd配置一个plist文件放到~/Library/LaunchAgents下再launchctl load就能常驻运行。日常办公自动化的需求cron通常就够用了launchd适合需要更精细控制场景的进阶用户。4.3 让脚本学会“说话”日志与异常通知无人值守运行里最尴尬的事是脚本跑挂了却没人知道。所以脚本不仅要会做事还要会留下记录、会在出事时喊人。最简单的做法是在调度的命令里把输出重定向到日志文件就像前面bat里写的那样。但如果想更进一步我建议在Python代码里使用内置的logging模块按需把信息写到文件并设置等级import logging logging.basicConfig( filenameorganize.log, levellogging.INFO, format%(asctime)s %(levelname)s %(message)s, encodingutf-8 )把原来print的地方改成logging.info(...)、logging.warning(...)。普通运行只有几行INFO异常时能留下完整的堆栈。我自己的习惯是本地手动跑时在终端看输出定时任务运行时看日志文件真正重要的脚本再加上异常通知。异常通知的落地方式很多邮件SMTP和各类webhook机器人是最常见的。关键点是只在异常时通知别把每条信息都发出来——如果每天定时任务正常跑却发给你一封“今天移了42个文件”的邮件时间一长你就会把通知当成垃圾真正出事时反而被忽略。只有失败才响警报才是对“通知”这一渠道的正确使用。4.4 无人值守的关键脚本的幂等性设计再补一个很多人忽略的重要概念幂等性。就是说同一个脚本无论被连续跑多少遍结果都应该保持一致、不产生脏状态。用整理文件举例第一次跑把散乱文件归档了第二次跑如果脚本又重新把源目录里的文件“重复移动一遍”那是没问题的因为源目录已经没文件了。但如果脚本设计成“把目标目录里的文件再按另一个规则处理”或者“把每个文件复制一份”跑两次就会复制出两份这就是糟糕的幂等性。我的原则很简单脚本运行时先做“是否还有待处理对象”的判断而不是无条件执行全套动作。例如定时同步类、清理类脚本都应该以“当前状态下还有什么要做”为导向而不是“我把预设动作做一遍就完”。5. 再往前走一步工具链、测试与边界5.1 从单脚本到工具链参数化与配置分离第一个版本跑通后你会很快发现需求变化的苗头今天要整理下载文件夹明天要整理桌面的单个目录后天又要给归档文件加一层“客户名”目录。如果这些变化全靠改代码迟早要乱。这时候就该做参数化与配置分离。所谓配置分离就是把“规则”从“逻辑”里拿出来。比如分类规则可以进一步挪到JSON或YAML文件里代码只负责读配置、执行动作。工具选型上如果参数开始变多可以把argparse换成click通过装饰器定义参数可读性会好很多如果项目要做批量操作、定时任务分发再考虑引入启动脚本或pipeline式编排。另外顺带说一句不只命令行有“脚本”概念。像Illustrator这类设计软件也有开源的脚本扩展生态本质上是把重复的批量导图、批量改图层名操作交给代码。如果你经常碰这类软件不妨留意下它们的脚本接口凡是两分钟以上的重复手工动作基本都有一条脚本化的路。我见过很多Python自动化项目死在“只写执行、不写维护”上。脚本刚写成时充满成就感但三个月后回来看当初那句“这里我以后再补”的注释已经变成了一笔技术债。所以参数化和注释不是给别人的是给三个月后的自己的。5.2 用pytest给自动化脚本上保险自动化代码和普通业务代码有个明显区别它跑起来的时候往往没有人盯着。白天你写业务代码跑挂了立刻有报错但半夜两点定时任务跑挂可能直到三天后你才发现三天前的数据没处理。所以自动化脚本比一般代码更需要自动化测试。对上面这个整理例子的organize.py我会为关键的规则逻辑写pytest测试import pytest from organize import get_category, build_target_path def test_get_category_pdf(): assert get_category(.PDF) 文档 def test_get_category_unknown_extension(): assert get_category(.xyz) 其他 def test_build_target_path_reuses_existing_month_folder(tmp_path): source tmp_path / report.pdf source.write_bytes(bfake pdf) target build_target_path(source, tmp_path / sorted, 文档, .pdf) assert target.parent.name 2024-01 assert target.parent.parent.name 文档像pytest这类自动化测试框架日常工作里最大的价值就是允许你频繁、安全地改代码。文件分类规则未来一定会变比如增加新扩展名、调整目录层级。如果没有测试每次改动都心惊胆战有了测试之后执行一下pytest绿了就是稳妥了。我给自己的项目定了个底线规则涉及文件删除、移动、网络请求的脚本至少给核心函数写10个左右的测试用例。这不需要花多少时间却能避免绝大多数低级回归。5.3 GUI与浏览器自动化工具怎么选克制是最高级的自动化前面讲的都是处理“文件”和“数据”层面日常工作里还有一类场景是“操作界面”比如登录网页下载报表、在软件里点按钮导出数据。这类需求有很成熟的工具栈浏览器自动化的Playwright、Selenium移动端有Appium、maestro甚至还有影刀RPA、Cheese这类面向业务人员的低代码自动化工具。但我要说一句逆耳的话GUI自动化是自动化里维护成本最高、坑最多的一类能不碰尽量不碰。原因也很直白界面是为人类设计的按钮位置、窗口大小、网络延迟都会让脚本失灵。你写20行代码让浏览器自动点一个按钮需求方一句话“页面改版了”你的20行代码就得从选择器开始重写。这类工具还有“模拟鼠标操作桌面软件”的方向我见过有人问股票软件能不能用鼠标自动化去代替手工操作我的建议非常明确不要做。一方面行情波动瞬息万变脚本处理异常的能力远不如人另一方面绕过软件正常交互流程去模拟操作很可能违反软件的用户协议。如果真要盯盘或做策略回测优先找官方API或官方允许的扩展方式这才是可持续的路。如果确实需要GUI自动化我建议用浏览器优先方案Playwright带无头模式、自动等待、网络断言稳定性比早期工具好很多同时做足等待策略和失败重试。能用官方接口实现的永远优先于界面自动化能改业务流程省掉的永远优先于写代码硬扛。5.4 关于合规与边界有些“自动化”真的不能碰聊到自动化就必须面对一个现实有些需求表面上是“效率工具”实质越界了。比如某些攻击类脚本、游戏作弊类脚本以及未经授权抓取他人数据的爬虫这类东西我没有立场教你也不会在文章里给任何实现思路。它们对你的职业生涯和技术能力积累没有任何正收益反而会带来实实在在的风险。哪怕是看着人畜无害的数据抓取也要先看目标站点是否有官方API、是否有明确的服务条款。我遇到过“自动化爬取页面时遇到woff字体混淆、页面数据抓出来是乱码”的求助这种技术本质上是在和反爬体系对抗。正确姿势是退一步查官方开放平台、合作关系或换个有授权数据的渠道。技术方案再巧妙如果前提不成立结果都是白费还可能惹上麻烦。规则不清晰时不要抱着侥幸心理硬上这是我在这行非常强烈的建议。6. 常见问题与排查技巧实录6.1 脚本一闪而过、命令找不到、路径报错自动化脚本跑不起来的原因说来说去就那几类。我整理了一张速查表遇到问题先按表排查症状最常见原因处理方式双击bat一闪而过脚本跑完正常退出输出没来得及看打开cmd手动执行或末尾加 pausepython不是内部或外部命令安装时没勾选Add Python to PATH安装Python时勾选或手动添加环境变量pip安装包后脚本仍ImportError装错了解释器环境全局 vs venv命令行确认 which python激活正确venvPermissionError文件被占用或当前用户无写权限关闭占用程序检查目录权限必要时用管理员权限读取文件名乱码/UnicodeDecodeErrorWindows下默认编码问题打开文件时显式指定 encodingutf-8定时任务没有执行计划任务里的程序/参数没用绝对路径检查任务属性程序填venv里的python绝对路径工具命令无法被识别如pnpm、Python等PATH未配置或终端还是旧窗口重新打开终端检查环境变量pip下载超时网络到源站不稳定配置国内镜像源比如清华PyPI镜像这里想特别展开两个高频问题。第一个是编码问题Windows下Python读取文件或文件名时经常碰到UnicodeDecodeError。解决方案就是前面表里写的所有打开文件的操作尽量显式写encodingutf-8必要时对读取的文件名做容错处理。第二个是“定时任务没跑”的排查顺序先手动执行一遍任务里的命令看能否正常完成再确认计划任务的触发器设置是否正确最后看程序是否用了绝对路径。绝大多数定时任务问题三步之内就能定位。6.2 文件操作类脚本的“后悔药”方案操作文件的脚本我建议在架构上就给它铺好后路。除了前面讲过的dry-run还可以在移动前先把原文件路径记在一份日志或CSV里这样即使出了乱子也能照着清单恢复。有人可能觉得这是“多此一举”但真经历过一次误移动几百个文件的痛苦就会明白这多出来的两三行代码有多值钱。除此之外涉及删除操作的脚本我默认不提供物理删除能力而是移到一个名为trash的目录定期人工清理。删除是危险操作中最危险的一种它发生在毫秒之间后悔程度却可以持续很久。让脚本慢半拍、多留一步缓冲这不是笨是对真实文件系统的敬畏。6.3 我的排障心法二分法与最小复现最后分享一个通用的排障思路当脚本报错但又说不清哪里错时不要盯着几百行代码反复看而是用二分法找问题。具体做法是先确认脚本在哪一行开始输出与预期不符加几个关键位置的调试打印或者复制出一段“最小复现”的sample数据人为触发问题。把问题范围从“整个项目”缩到“一个函数”再到“一行代码”通常速度最快。我在调试那个文件整理脚本时曾遇到“有的文件归档成功有的文件静默消失了”。当时我没有直接怀疑代码逻辑而是把消失的那个文件路径单独拿出来跑了一遍这才发现目标目录的月份子目录创建失败导致shutil.move抛异常被上层逻辑吞掉了。发现过程没什么神奇就是通过打印每步的实际状态把范围一步步缩到那个目录权限上。这个习惯后来帮我省了无数时间。最后一点真实体会一个脚本真正成熟的标志不是它第一天跑通时的兴奋而是它连续运行一个月后你几乎忘记它的存在。我后来给整理脚本加上了日志、异常邮件提醒和pytest测试它就像一个沉默的值班员每天在固定时刻出现把那些琐碎但必须做的事情处理完。自动化带给我的解放感不是“我再也不用做这些事了”而是“我终于有精力去做那些机器做不了的事了”。如果你正打算动手写第一个脚本我的建议是从最小的场景开始先让它跑起来再逐步优化。好的自动化项目从来都是长出来的不是一开始设计出来的。
返回列表