
1. 为什么要先用Python打好自动化地基提到自动化大多数人第一反应是RPA、按键精灵、定时任务这些工具。但作为跑了几年自动化脚本的人我真心建议先把Python基础啃扎实。理由很简单——市面上绝大多数自动化框架不管是办公自动化、爬虫、还是运维批处理的底层或接口都向Python敞开不会Python你只能在别人封装好的功能边缘打转遇到稍微刁钻一点的需求就卡住了。这一篇不做花哨的东西就是把Python知识点里和自动化最相关的基础概念拆开揉碎讲清楚。定位是自动化系列的第一课适合刚接触编程、或者以前学过但没怎么写自动化脚本的人。看完这篇你应该能理解变量、数据类型、流程控制、函数、文件操作这些“积木”各自长什么样以及它们将来怎么组合成自动化脚本。我见过太多人一上来就怼着爬虫库、自动化库学结果HTTP状态码、正则表达式、异常处理这些基本功全是窟窿后面排查问题寸步难行。Python基础不追求大而全优先掌握自动化脚本里高频出现的那些点才算把力气用在刀刃上。2. Python环境准备与开发工具选型2.1 环境问题不解决后面全是坑先说环境。Windows和macOS用户直接去Python官网下载安装包安装时记得勾选“Add Python to PATH”这一步漏了后面在命令行敲python会提示“不是内部或外部命令”。Linux发行版一般自带Python3但版本可能偏老如果自带2.x或者比较旧的3.6建议用系统包管理器装一个较新的版本。可以打开终端输入python3 -V确认版本号优先选择3.8以上的版本自动化生态里常用的依赖基本都已经完整适配。这里要强调一下创建虚拟环境是我认为最值得养成的习惯。Python项目多了之后不同项目依赖的包版本可能互相冲突——比如A项目要用requests 2.xB项目要用某框架新版本恰好不兼容。虚拟环境相当于给每个项目造了一间独立房间互不干扰。创建方式很简单在项目目录里执行python -m venv venvWindows下激活命令是venv\Scripts\activatemacOS和Linux是source venv/bin/activate。看到命令行前面出现(venv)字样就说明已经进入虚拟环境了。之后用pip安装的包都只在这个环境里生效不会污染全局环境。2.2 IDE和编辑器怎么选很多Python新手纠结用什么编辑器。其实工具只要满足两点就够了一是能高亮语法二是能直接运行脚本。我最初用记事本和命令行写了将近两个月这样做的好处是倒逼你把语法记得很牢坏处是出错时找个括号都不方便。如果非要推荐VSCode加Python插件是性价比较高的方案免费、插件生态丰富、调试功能也直观。装好后只需要学会一键运行当前Python文件以及看到代码提示不需要过多折腾插件配置。另一个方案是PyCharm Community Edition它对工程管理更友好适合将来写稍大型的项目。不管选哪款学基础阶段最重要的是把注意力放在语言本身而不是编辑器主题、插件美化这些事上。3. 核心语法基础变量、数据类型与运算符3.1 变量在Python里本质上是个标签先理解变量是什么。大多数编程语言里变量是一个用来存数据的容器但Python更准确的理解是——变量是贴在对象上的标签。数据对象在内存里有一个位置你用变量名去引用它。这就解释了为什么Python里能把同一个列表赋值给两个不同变量它们指向的是同一份数据修改其中一个另一个也会变。变量命名遵循几条约定俗成的规则只能由字母、数字、下划线组成不能以数字开头不能用Python内置关键字比如if、for、class命名命名风格推荐使用蛇形命名法——全小写单词之间用下划线分隔比如file_path、retry_times。这样的命名在自动化脚本里特别常见因为本身就是在描述“你要操作什么文件、要重试几次”。3.2 五个必须掌握的基础数据类型Python的常用内建数据类型按自动化使用频率排序我认为最重要的是字符串、整数与浮点数、布尔值、列表、字典。元组和集合适当了解即可。字符串在自动化里无处不在——不管是文件路径还是抓取下来的网页内容都被当作字符串处理。字符串可以用单引号或双引号包裹两者在功能上没有区别。需要特别注意的是转义字符比如路径C:\Users\xxx直接在字符串里写会遇到反斜杠转义问题。两种解决思路一个是在字符串前面加r变成原始字符串例如rC:\Users\xxx另一个是把反斜杠写成双反斜杠。我在处理Windows路径时几乎无脑用r前缀读者也可以养成这个习惯。整型和浮点型主要是用来做数值计算的比如统计文件数量、计算任务执行时间。布尔值只有True和False两个取值常用于条件判断。这三个类型本身难度不大容易犯错的地方在于类型转换——input()函数读到的任何内容都是字符串如果要做加减运算必须用int()或float()显式转换。3.3 运算符的几个容易踩坑的地方算术运算符里最需要注意的是除号。Python 3里单个/得到浮点数结果7/2等于3.5这符合直觉。但整除符//得到向下取整的整数结果7//2等于3。做任务计数时如果不小心用错结果会差出不少。取余运算符%在判断奇偶、循环任务分组这些场景里很有用。比较运算符的坑在“等于”这里等号是赋值两个等号才是判断相等。新手容易在if条件里少写一个等号代码会直接报语法错误倒还好排查。比较链式写法在Python里比较优雅比如0 x 10可以直接写这点比很多语言舒服。逻辑运算符是and、or、not这三个英文单词而不是其他语言常见的或||。记忆逻辑结果时只需要记住几条规律and两边都是真才为真or只要一边为真即为真not把真变假、假变真。看到代码里出现if file_exists and file_size 0这样的写法就是典型的多条件同时成立的场景。3.4 字符串的进阶操作格式化是自动化脚本高频动作自动化脚本里字符串做拼接和格式化的频率极高。比如你要生成一个带日期的文件名report_20250115.txt不可能手写日期到文件名里必然要动态拼接。三种常见方式加号拼接、%占位、format方法、f-string。我目前在自动化脚本里几乎只用f-string因为最直观。写法是在字符串前加f然后在大括号里直接写变量或表达式today 20250115 filename freport_{today}.txt print(filename) # report_20250115.txt写日志时这种格式特别方便比如打出一条带时间、任务名、状态的日志用f-string一行搞定。注意大括号里的表达式会被求值所以f{a} {b} {ab}这样带计算的写法也完全合法。字符串还经常需要切割和查找。split()方法按指定字符把字符串拆成列表join()把列表里的元素用指定字符串连接起来这两者经常配合CSV或日志解析使用。strip()去掉字符串两端的空白字符或换行符在处理从文件读到的每行文本时几乎是必用操作。4. 流程控制自动化脚本的指挥棒4.1 if条件判断让脚本根据情况走不同分支自动化脚本最有价值的点之一就是能根据不同的条件决定执行什么动作。if语句的基本结构是if、elif、else。Python用缩进表示代码块同一层级的代码必须缩进一致——这个设计的好处是强制写出的代码本身就比较整齐坏处是新手容易混用空格和Tab导致报IndentationError。平时写自动化逻辑经常见到多条件判断比如判断文件是否存在存在才处理不存在就打日志跳过判断接口返回状态码是否是200是就解析数据否则告警重试。这些场景都可以用if结构来描述。elif的匹配顺序是从上往下命中一个分支就不会再往下走。如果条件相互之间可能有重叠注意要把更具体的条件放在前面。4.2 for循环自动化处理大批量任务的核心日常自动化里用得最多的是for循环因为拿到的数据往往是一组一组来的——一个文件夹里的所有文件、一个列表里的所有订单号、一个CSV里的所有行。对每个元素挨个处理就是for循环的核心用法。遍历可迭代对象的通用写法是for item in iterable。遍历列表最常见遍历字典时这边也提一下直接用for key in dict拿到的是键想同时拿键和值可以用items()方法config {host: 192.168.1.10, port: 8080} for k, v in config.items(): print(f{k} {v})结合range()可以实现按次数循环。range(5)生成0到4的整数序列从0开始是Python和其他主流语言一致的默认行为。需要步长时写range(1, 10, 2)得到的是1、3、5、7、9。在自动化脚本里range常用来控制重试次数比如某任务最多尝试3次就可以用for attempt in range(3)配合break写。4.3 while循环条件不满足就一直等与for循环不同while循环是只要条件成立就反复执行。自动化脚本里常用while来做“等待某个条件满足”的操作比如轮询接口直到状态变成“已完成”或者等待某个文件被生成出来。但while循环最大的风险是死循环——条件永远为真程序永远不会退出。避免死循环的几个实用习惯确保循环体内一定有让条件趋向于False的操作或者用计数器控制最大循环次数实在担心就加一个time.sleep()降低循环频率避免CPU空转。max_retry 5 attempt 0 while attempt max_retry: # 尝试执行某项任务 success False if success: break attempt 1 else: print(重试次数用尽任务失败)这里while后面的else可能很多人没见过它是循环正常结束没有被break跳出时执行的分支在“重试次数用完”这种场景下特别合适。4.4 break、continue与pass的使用心得break是终止整个循环continue是跳过当前这次迭代、进入下一次。写这两者的区分时给新手一个口诀break是“到此为止”continue是“跳过这次”。pass在Python里是空语句什么都不做。它主要用在语法上需要语句但逻辑上还不想写实现的时候比如先搭好函数框架函数体里写个pass占位保证代码能通过语法检查。在自动化脚本的开发阶段我经常用pass给“暂时不需要处理”的异常分支占个位置。5. 函数自动化脚本的积木块5.1 为什么脚本要拆函数如果写一个100行的自动化脚本全部堆在顶层运行是能运行但维护时你会想骂人。把所有逻辑都写在最外层的问题是变量之间互相引用、顺序逻辑交错改一个地方容易牵扯其他地方。函数的本质是把一段逻辑封装起来给它起个名字、定义好参数调用时只需要关心输入和输出不关心内部实现细节。自动化脚本里函数的典型划分大概是这样连接数据库做一个函数拉取数据做一个函数处理数据做一个函数写入结果做一个函数。将来任何一个环节出问题直接定位到对应函数去改不会殃及旁边的逻辑。定义函数的语法是def加上函数名和括号括号里是参数列表参数可以有默认值。调用时按位置传参之外还可以用关键字传参也就是在调用时写明参数名这样可读性提升很多def download_file(url, timeout30, retry_times3): pass # 具体下载逻辑download_file(url)这样调用时timeout和retry_times会用默认值也可以download_file(url, timeout60)只覆盖其中一个。5.2 return返回值函数和调用方之间的桥梁函数可以没有返回值也可以返回任意类型的数据。自动化脚本里一个函数干的活通常是“计算出一个结果然后交给外面用”比如写一个解析日志的函数返回提取出来的错误码列表。多个返回值可以用逗号分隔返回接收时也按同样方式解包def get_server_info(): return 192.168.1.10, 8080 ip, port get_server_info()返回值既可以在调用方里赋值给变量也可以直接放进其他表达式里参与运算、拼接。有一点要注意函数执行到return语句就立即结束return后面的代码不会执行。所以把return放在函数体中间来控制提前退出是一种常见写法比如循环里找到目标元素就直接return不需要再遍历剩下的部分了。5.3 变量作用域为什么函数里改不了外面的值新手最容易困惑的作用域问题。函数内部赋值的变量默认是局部变量只存在于函数内部。如果函数里写了global x来声明要改变全局变量x虽然可行但我不太推荐大量使用global——全局变量被多个函数随意改动时代码会变得很难追踪。实际开发里更推荐的做法是函数不直接改全局变量而是通过参数传入、通过返回值把结果带出来。这样数据的流向很清晰不会出现“咦这个全局变量在哪里被改了”这种耗费大量时间排查的情况。count 0 # 全局变量 def add_one(n): n 1 return n count add_one(count)这里把count传给函数得到新值后再赋回给count既不污染全局变量也让逻辑一目了然。自动化脚本里这种“传入一份数据处理后返回一份新数据”的模式比直接改全局状态安全得多。6. 数据容器深入列表、字典、元组、集合的实战场景6.1 列表有序可变的自动化任务清单列表是一个有序的、可以修改的元素集合在自动化脚本里可以用它来表示一个任务清单或者一组目标文件。append()往末尾加元素extend()把另一个列表的元素扩展进来insert()在指定位置插入remove()按值删除pop()按下标弹出并返回被删除的元素。列表切片的语法值得反复练li[start:end:step]start和end都是左闭右开——包含start位置不包含end位置。这个规则Python里到处一致字符串也是一样。切片返回的是新的列表不会修改原列表。排序用sorted()函数返回新列表或者用列表的sort()方法原地排序。如果列表元素是复杂对象可以用key参数指定排序规则比如按字典里的某个键排序tasks [ {name: 报表生成, priority: 3}, {name: 数据备份, priority: 1}, {name: 日志清理, priority: 2}, ] tasks.sort(keylambda x: x[priority])6.2 字典键值对的配置中心字典是Python里最接近“配置文件”的天然数据结构。自动化脚本读取配置文件后通常就是拿到一个字典。字典以键值对的形式组织数据键必须是不可变类型常用字符串或元组值可以是任意类型。通过键取值的效率很高因为它底层是哈希表实现。使用字典时有几个安全习惯。用d[key]取值如果键不存在会直接抛KeyError。更稳妥的做法是用d.get(key, default_value)键不存在时返回默认值而不报错。批量构造字典用dict()或者花括号直接写从两个列表合成一个字典可以用zip()配合dict()keys [host, port, username] values [192.168.1.10, 8080, admin] config dict(zip(keys, values))遍历字典的场景也很多前面提过items()方法。检测一个键是否存在于字典中用in操作符很自然比如if host in config:。6.3 元组不可变的轻量级数据结构元组和列表的区别主要是元组创建后不能修改。这个特性让元组在某些场合比列表更安全——比如函数要返回多个值直接返回一个元组是Python的常见习惯。另外元组可以作为字典的键列表不能因为列表可变、不可哈希。定义只有一个元素的元组时注意要写(1,)加一个逗号否则被解释成普通括号表达式。这个细节虽然小但确实在代码里见过有人被它坑到。6.4 集合去重和集合运算利器集合的特点有两个元素不重复、无序。在自动化脚本里最常用的场景是去重——比如从多个日志文件里收集所有IP地址放进集合天然就去掉了重复项。另一个高频用法是集合运算求并集|、交集、差集-可以用来对比两个文件里的内容差异。current_ips {192.168.1.1, 192.168.1.2} allowed_ips {192.168.1.2, 192.168.1.3} blocked current_ips - allowed_ips6.5 列表推导式与字典推导式一行写出循环逻辑推导式是我非常喜欢Python的原因之一。原本三五行才能写出来的循环加条件逻辑用推导式一行完成代码简洁、可读性也好。最常见的列表推导式结构是[表达式 for 变量 in 可迭代对象 if 条件]files os.listdir(./datadir) csv_files [f for f in files if f.endswith(.csv)]字典推导式结构类似只是用冒号把键值表达式分开file_sizes {f: os.path.getsize(os.path.join(./datadir, f)) for f in files if f.endswith(.csv)}推导式虽好也不要滥用——如果逻辑过于复杂嵌套好几层循环和条件强行压缩到一行反而会牺牲可读性。经验准则是能一行读懂就用推导式否则老老实实写普通循环。7. 文件读写与路径处理自动化脚本的基本功7.1 路径处理少踩Windows和macOS的坑自动化脚本里操作文件最容易出问题的就是路径。Windows系统用反斜杠\分隔路径macOS和Linux用正斜杠/。如果手动拼接路径字符串换一台电脑就跑不动了。正确做法是用os.path模块或者直接只用pathlib模块。pathlib是Python 3.6之后引入的现代路径处理方式强烈建议把路径操作统一用它来做。from pathlib import Path base_dir Path(./data) file_path base_dir / report.csv这里Path对象用斜杠运算符直接拼接子路径完全不用关心操作系统是什么。Path自带的方法比如exists()判断是否存在、is_file()判断是否是文件、mkdir(parentsTrue, exist_okTrue)创建目录可以一次性创建多级目录且已存在时不报错、glob()按通配符匹配文件。7.2 文本文件的Read和Write读文件的推荐方式是用with语句好处是无论正常运行还是中途出错都会自动关闭文件不用手动写close()。完整读写一个文本文件的经典代码with open(input.txt, r, encodingutf-8) as f: content f.read() # 读取全部内容 lines f.readlines() # 或者按行读取成列表写文件时用模式w会清空原文件再写如果不想覆盖而是追加用a模式。编码问题也是自动化脚本的常见坑——读写文本文件时尽量显式指定encodingutf-8避免不同平台上默认编码不同导致的乱码。一定要记住处理历史遗留中文文件时源文件可能确实是GBK编码这时读取时需要指定encodinggbk。做文件编码转换是很多自动化办公脚本的核心功能所以这块建议大家多加练习。按行处理大文件时不要一次性read()整个文件到内存里而是直接for line in f逐行迭代with open(large.log, r, encodingutf-8) as f: for line in f: if ERROR in line: print(line.strip())7.3 处理CSV办公自动化里的高频场景解析CSV不要自己split逗号——因为CSV里的字段可能包含逗号、引号和换行自己处理边界条件很容易出错。正确做法是用Python标准库里的csv模块import csv with open(data.csv, encodingutf-8, newline) as f: reader csv.DictReader(f) for row in reader: print(row[姓名], row[部门])写CSV时用csv.writer配合writerow()可以逐行写入。如果数据量巨大可以考虑批量构造列表后调用writerows()一次写入。特别注意newline这个参数——Windows下不指定它可能会在每行后面多写一个空行这算是一个反复出现的小坑。7.4 JSON和网络接口打交道必备自动化脚本经常要和API接口交互而现代API接口最常用的数据格式就是JSON。Python标准库json模块提供了loads字符串转字典或列表和dumps字典或列表转字符串两个核心函数。import json data {name: 备份任务, status: success, files: 32} json_str json.dumps(data, ensure_asciiFalse, indent2)indent参数让输出更好看ensure_asciiFalse让中文保持原样而不是转成\uXXXX的形式。读取JSON文件用json.load()。这些操作在解析接口返回值、读取配置文件的场景里出现频率极高。8. 异常处理自动化脚本的护栏8.1 不处理异常的自动化脚本走不远自动化脚本和普通脚本最大的不同在于它往往是无人值守运行的半夜定时任务跑着跑着报错了不会有人盯着控制台看。如果不处理异常一个无关紧要的文件缺失就能让整个任务链中断。Python的异常处理语法是try、except、else、finally。基本写法try: result 10 / 0 except ZeroDivisionError: print(除数不能为0) except Exception as e: print(f发生未知异常: {e})except可以捕获指定的异常类型一个try可以跟多个except处理不同异常。不想让脚本中断就在except里处理好之后让代码继续走。捕获所有异常的兜底写法是except Exception会比裸的except BaseException更可控一些。8.2 finally与else资源清理和正常分支finally块无论是否发生异常都会执行所以它适合放清理代码比如关闭数据库连接、删除临时文件。else块在try里没有异常时执行这个用得相对少但可以让“正常走的逻辑”和“出错的逻辑”在结构上分得更清楚。try: f open(config.json, encodingutf-8) data json.load(f) except FileNotFoundError: print(配置文件不存在使用默认配置) except json.JSONDecodeError: print(配置文件格式错误) else: print(配置文件加载成功) finally: if f in locals(): f.close()这段代码在自动化启动流程里很典型——加载配置时可能遇到多种异常每种异常的处理方式不一样finally确保文件最终被关闭。8.3 主动抛出异常与自定义异常有些时候代码本身没有报错但从业务角度看是异常情况比如配置里端口号写了负数、接口返回状态码不是200。这种情况可以主动抛异常raise ValueError(端口号不能为负数)。主动抛异常的好处是让错误在上层统一被捕获处理而不是在底层静默返回错误值然后一路散播。日志记录配合异常处理也是一对常见的组合。捕获到异常后不仅要在控制台打印信息还应该写入日志文件import logging logging.basicConfig(filenameapp.log, levellogging.INFO, format%(asctime)s - %(levelname)s - %(message)s) try: pass # 核心操作 except Exception as e: logging.error(f任务执行失败: {e})把错误时间、错误类型记录下来第二天早上检查日志就能定位问题这比异常信息一闪而过要好得多。9. 常用内置模块自动化脚本的弹药库9.1 os和sys操作系统交互os模块是Python和操作系统打交道的门户。nlistdir列出目录下的文件名os.name判断操作平台os.environ读取环境变量os.getcwd获取当前工作目录。虽然很多路径高级操作用pathlib更顺手但os模块仍然广泛存在包括第三方库内部通常也是基于它实现的所以至少要看得懂。sys模块经常配合脚本参数使用。sys.argv是一个列表第一个元素是脚本文件名后面的元素是命令行传入的参数。在自动化任务里会给脚本传参数比如python run_task.py --envproduction用sys.argv可以拿到--envproduction去解析。如果想解析得更优雅可以使用标准库argparse但那属于另一块进阶内容了。9.2 datetime与time时间处理是自动化的命脉自动化任务几乎绕不开时间定时执行、给文件加时间戳、计算任务耗时、判断是否超时。time模块偏底层一点time.sleep(seconds)是延时的常用函数在重试逻辑和限频控制中必不可少。time.time()返回当前时间戳浮点数秒数两次调用相减可以得到时间差。日常日期处理更推荐datetime模块。datetime.datetime.now()可以获取当前时间datetime.timedelta可以表示时间间隔直接做加减操作from datetime import datetime, timedelta now datetime.now() yesterday now - timedelta(days1) date_str now.strftime(%Y%m%d_%H%M%S)strftime格式化日期是高频操作生成的date_str可以用在文件名里比如backup_20250115_233001.zip这样每次执行任务生成的文件都不会重名。9.3 subprocess在脚本里调用外部命令自动化脚本做系统管理时经常需要调用外部命令比如压缩文件、启动某个服务、执行数据库备份命令。subprocess模块就是干这个的推荐使用的接口是subprocess.run()import subprocess result subprocess.run( [ping, -c, 3, 192.168.1.1], capture_outputTrue, textTrue ) print(result.stdout)run()会阻塞等待命令执行完成。capture_outputTrue可以捕获命令的标准输出和标准错误textTrue把输出解码成字符串。注意不要直接拿shell字符串去执行——除非你完全信任输入内容否则在自动化脚本里组命令强烈推荐使用参数列表形式避免注入类问题。9.4 hashlib与re校验与文本抽取hashlib用来计算MD5、SHA256这些摘要。自动化下载脚本里校验文件完整性、或者对比两个文件内容是否一致都离不开它。re正则表达式是一个更大的话题。在自动化处理文本时比如从日志里提取错误码、从网页内容里抽取邮箱或链接用字符串自带的方法往往力不从心正则才是正确解法。最常用的操作是re.search找匹配、re.findall找所有匹配、re.sub替换匹配内容。正则的模式语法本身需要专门学习但Python调用方式本身很简单遇到具体场景再逐步积累模式写法是我比较推荐的学习路径。10. 组合实践从零写一个自动化脚本雏形10.1 需求拆解把问题翻译成代码逻辑前面拆了很多知识点找一个具体的自动化场景把它们串起来。设想一个常见的需求每天扫描某个目录下所有的CSV文件统计每个文件的行数把结果写入一个汇总报告。把它拆成一小步一小步的思路用pathlib列出目录下所有.csv文件2. 逐个读取文件并计算行数3. 把文件名和行数组装成字典4. 把结果写入一个新的CSV文件5. 如果某个文件读取失败记入日志而不是中断整个任务。10.2 代码实现一行一行说清楚from pathlib import Path import csv import logging from datetime import datetime logging.basicConfig( filenamescan_report.log, levellogging.INFO, format%(asctime)s - %(levelname)s - %(message)s ) def count_lines(file_path: Path) - int: # 计算文件行数 try: with open(file_path, encodingutf-8) as f: return sum(1 for _ in f) except Exception as e: logging.error(f读取文件 {file_path} 失败: {e}) return -1 def main(): data_dir Path(./datadir) today_str datetime.now().strftime(%Y%m%d) output_path Path(fsummary_{today_str}.csv) csv_files list(data_dir.glob(*.csv)) logging.info(f找到 {len(csv_files)} 个CSV文件) rows [] for file_path in csv_files: line_count count_lines(file_path) rows.append({ file_name: file_path.name, line_count: line_count }) with open(output_path, w, encodingutf-8, newline) as f: fieldnames [file_name, line_count] writer csv.DictWriter(f, fieldnamesfieldnames) writer.writeheader() writer.writerows(rows) logging.info(f汇总报告已写入 {output_path}) if __name__ __main__: main()10.3 逐步解析这段代码为什么这么写count_lines函数里用sum(1 for _ in f)逐行迭代并计数相比readlines()再len()的方式它对大文件更友好——逐行迭代不会把整个文件一下子载入内存。用-1来表示读取失败的行数这样汇总报告里能直观看到哪个文件有问题同时又不会让类型上出错。在写这个函数时我特意加了类型注解Path不是必须的但它能提高可读性也方便代码提示。main函数里的逻辑顺序就是前面拆解的步骤。data_dir.glob(*.csv)是pathlib提供的高效匹配接口返回的是迭代器用list()转成列表是为了后面的统计操作。给输出文件加时间戳是为了避免每天运行覆盖以前的报告同时保留历史记录。异常处理选择的策略是单文件失败只记录日志让主流程继续这样某个文件损坏不会连累整个目录的任务但如果目录本身不存在glob会直接返回空列表而不是报错这属于pathlib和os.path不太一样的地方值得记住。ifname main这个写法初学者可能觉得奇怪它保证当前文件作为主程序运行时才执行main()如果文件被别人import为模块main不会被自动调用这是Python工程里约定俗成的入口写法。11. 新手答疑我经常被问到的Python基础问题11.1 学完基础马上够用了吗基础语法只是第一步学完“变量、循环、函数”大概能看懂和写一些小型脚本但真实自动化项目往往涉及第三方库、网络请求、数据库、正则表达式、任务调度这些都要按需补充学习。我的建议路线是先把这一篇里的知识点吃透每个代码示例都亲手敲一遍然后尝试改造它们应用在自己的需求里。至于Git、dedug调试技巧这些在初学阶段不用急着搞明白用到再学反而记得更牢。11.2 记不住语法怎么办这是一个高频焦虑点但完全正常。Python语法细节太多了f-string参数、列表推导式的顺序、异常处理的结构没人能一次性全记住。我自己写代码时还经常查阅文档重点不是背下来而是遇到问题知道去哪里查。实用技巧是给常用操作建一个笔记清单比如“如何读CSV”“如何遍历字典”“如何格式化日期”每次查过一遍就记录一次多记几次自然就入脑了。俗称“抄作业抄到最后就是自己的”。11.3 代码里中文乱码怎么回事文章前面多次提到编码问题。Python 3里字符串是Unicode但文件读写、控制台输出、网络传输各有各的编码一旦不对接就会乱码。三个思路读写文件时显式指定encodingutf-8控制台输出中文乱码则检查终端编码设置抓取网页内容时优先用响应对象里告诉你的编码方式而不是硬猜。11.4 自动化脚本跑得很慢有哪些优化空间初学阶段先不要过度优化。如果真的遇到性能问题第一反应是定位瓶颈在哪——是IO等待读写文件、网络请求还是CPU密集计算。简单计时可以用time.perf_counter()包住目标代码段。如果是处理大量数据可以考虑用csv模块分批读写、用生成器替代一次性载入列表、用多线程或多进程并行处理。这些优化手段之后可以展开聊但现阶段先把功能跑通比性能重要得多。12. 踩坑实录Python自动化新手容易掉的坑12.1 在Windows下跑文件路径脚本Windows路径里的反斜杠和Python字符串转义组合是重灾区。如果你的脚本里写了open(C:\Users\test\data.txt)看起来没错但\U和\t在字符串里分别会被解释成Unicode前缀和制表符直接报错或者打开完全错误的文件。解决办法前面提过使用pathlib统一处理或者用r前缀。12.2 用判断浮点相等浮点数在计算机里是近似表示0.1 0.2不等于0.3这在很多语言里一样。当自动化脚本里涉及金额、精度比较或多次运算时绝对不要直接判断浮点结果相等。正确思路要么用round()取精度后比较高精度场合直接使用decimal.Decimal类型。12.3 修改列表时迭代它常见于删除列表元素的操作。在for循环里边遍历边删除列表元素结果会导致元素跳过或索引错乱。正确做法是创建新列表保存要保留的元素或者在遍历前复制一份列表出来items [x for x in items if x ! BAD]这一行推导式在“过滤掉不需要的元素”这个场景里足够清晰可靠。12.4 混淆深拷贝与浅拷贝列表直接赋值a b并没有创建新列表它只是让a和b指向同一个对象。修改a中元素b也会跟着变。用list(b)或b[:]可以生成浅拷贝但浅拷贝对于嵌套列表来说内层的子列表仍然共享。如果确实需要一个完全独立的副本用copy.deepcopy()。这块是自动化脚本容易埋雷的地方特别是在“把一份配置复制一份作为新任务的参数”修改副本结果影响原始数据的报错会很让人头疼。12.5 全局变量被意外修改前面讲过global关键字的问题。补充一个常见场景在函数里对没有global声明的变量做赋值操作如果这个变量名和某个全局变量重名Python会把它当作局部变量处理。有时候你在函数里只是想读取它的值却在某行不小心写了赋值操作于是报UnboundLocalError。遇到这种错误先检查函数内部的同名变量有没有被赋值过。13. 学习路线与实操建议13.1 从亲手敲示例到改造脚本看了这么多知识点不动手等于白看。我建议跟着这篇里的代码示例逐一自己敲一遍并跑出结果不要复制粘贴。敲完一遍之后尝试改动一些小地方比如把count_lines里的行数统计改成统计非空行数把输出格式改一改。改坏了再改回来这个过程建立的理解深度远比看十遍文章要强。13.2 用“小需求”驱动学习不用想着一次性掌握所有内容。选一个小而真实的需求比如“整理并重命名一个文件夹里的所有图片文件”慢慢拆解它需要哪些知识点遍历目录、字符串处理、文件操作、路径处理。边学边实践这个需求做完相关知识点基本就巩固了。之后再选下一个需求不断扩充自己的技能边界。我自己的经验是先定目标再围绕目标去查资料学习学习效率要比按部就班看书高得多。而且随着自己写过的脚本越来越多之前觉得抽象的语法会用得越来越顺手。13.3 建立代码资料库写过的代码不要扔。在本地目录建一个代码库文件夹按功能分类保存文件处理、网络请求、Excel操作、数据清洗、定时任务。往后做新项目时优先翻已有的代码能复用就复用。千万不要每次都从零开始代码复用是自动化领域效率的基本功。即使前期的代码写得很幼稚它们也是自己积累的财富。13.4 遇到报错先按这个顺序排查报错信息要完整读完不要只看最后一行。常见的排查思路先看错误类型是什么FileNotFoundError、TypeError、ValueError、IndexError再定位错误发生在哪一行对照那行的代码猜测原因——是变量没有定义、类型不对、索引越界还是路径不对。把print()当调试武器在可疑位置打印变量值确认逻辑走到哪一步时最接近现实。这条排查路径看起来朴素但它解决了我在新手时期遇到的绝大多数问题。等你跑完几十个报错再回头看很多基础知识点会有一种豁然开朗的感觉。14. 最后的补充为什么劝你先学Python再学自动化框架很多自动化框架都提供了“录制回放”或者“拖拽组件”的能力看起来完全不需要写代码。但真实的自动化需求永远比框架演示复杂——页面结构改版了、文件格式变了、异常情况出现了、业务规则调整了。不会写代码遇到这些变化就只能永远等框架更新会Python你可以自己调整逻辑去适配这份主动性就是无可替代的自由度。更重要的是Python的能力不止于自动化一种方向数据处理、定时任务、接口调用、GUI工具、甚至是简单的机器学习模型都用同一套语言基础。这也就是说你现在花时间打下的基础将来的复用价值远远超过“为了入门某个具体自动化工具”所投入的成本。我建议把这一篇当作起点把每个示例运行起来体会到一段脚本帮你省下重复劳动的快乐。记住作者踩过的种种坑然后在自己的代码里尽量避开。语言的学习从来不是“看完即会”而是“敲完才会”。下一篇开始逐步往上走等基础打牢了真正好玩的自动化世界大门才刚打开。