“一个月前,我还在手动复制粘贴Excel,每天加班半夜。现在,我坐在工位上泡杯茶,看着脚本自动处理全校成绩、生成报告、发邮件。这30天,我把踩过的坑、流过的泪、修过的bug都写成了文章。但我知道,很多人学完就忘,遇到问题还得翻之前的教程。今天我把这30天最常用、最实用的代码整理成一张表,每行代码都附上“自己踩过的坑”和“逐行解释”。以后再遇到类似任务,直接复制这段,改改文件名就能用。
import os, shutil# 列出文件夹里所有文件(排除文件夹)files = [f for f in os.listdir('目标文件夹') if os.path.isfile(os.path.join('目标文件夹', f))]# 移动文件shutil.move('旧路径', '新路径')# 批量重命名(加序号)for i, f in enumerate(files): new_name = f'文件_{i+1}.txt'if not os.path.exists(new_name): os.rename(f, new_name)# 创建文件夹(如果不存在)os.makedirs('新文件夹', exist_ok=True)os.listdir('目标文件夹'):拿到文件夹里所有东西的名字。os.path.isfile():判断是不是文件(不是文件夹)。shutil.move():移动文件到新位置。os.rename():重命名文件。os.makedirs(..., exist_ok=True):创建文件夹,如果已经存在也不会报错。os.path.isfile 过滤,结果把文件夹也移动了,整个目录结构乱掉。if not os.path.exists 判断。r'路径'或者双反斜杠 \\。import pandas as pd# 读取Exceldf = pd.read_excel('成绩表.xlsx', sheet_name='Sheet1')# 快速查看df.head() # 前5行df.info() # 列信息、缺失值df.describe() # 数值列统计# 处理缺失值df.dropna() # 删掉有缺失的行df.fillna(0) # 缺失填0df['语文'].fillna(df['语文'].mean()) # 用平均值填# 筛选数据df[df['班级'] == '三(1)班'] # 单条件df[(df['语文'] > 90) & (df['数学'] > 90)] # 多条件且# 新增列df['总分'] = df['语文'] + df['数学'] + df['英语']df['等级'] = df['总分'].apply(lambda x: '优'if x >= 270 else'良')# 分组统计df.groupby('班级')['语文'].mean() # 各班语文平均df.groupby('班级').agg({'语文':'mean', '数学':'max'}) # 不同列不同统计# 合并多个Excelall_files = [f for f in os.listdir('各班成绩') if f.endswith('.xlsx')]df_list = [pd.read_excel(os.path.join('各班成绩', f)) for f in all_files]df_all = pd.concat(df_list, ignore_index=True)# 保存df.to_excel('结果.xlsx', index=False)df.to_csv('结果.csv', index=False, encoding='utf-8-sig')pd.read_excel():读Excel,sheet_name 指定工作表。head()、info()、describe():快速了解数据。dropna()、fillna():处理缺失值。df[条件]:筛选行。groupby:分组聚合。pd.concat():纵向合并多个DataFrame。to_excel/to_csv:保存,index=False 去掉行号。from docxtpl import DocxTemplate# 加载模板doc = DocxTemplate('奖状模板.docx') # 模板里要有 {{姓名}}、{{奖项}} 占位符# 填充数据doc.render({'姓名': '张三','奖项': '三好学生','日期': '2025年7月'})# 保存doc.save('奖状_张三.docx')# 批量生成(配合pandas)import pandas as pddf = pd.read_excel('学生名单.xlsx')for _, row in df.iterrows(): doc = DocxTemplate('奖状模板.docx') doc.render({'姓名': row['姓名'],'奖项': row['奖项'],'日期': '2025年7月' }) doc.save(f"奖状_{row['姓名']}.docx")DocxTemplate('模板.docx'):加载Word模板文件。.render({...}):用字典里的值替换模板里的 {{变量}}。.save():保存为新文件。{% for row in 汇总表 %} 语法,但 docxtpl 的表格渲染比较绕,建议先在模板里画好一行,然后用{% for %}包裹。InlineImage,否则图片不显示。import PyPDF2# 合并多个PDFmerger = PyPDF2.PdfMerger()for pdf in ['1.pdf', '2.pdf']: merger.append(pdf)merger.write('合并.pdf')# 拆分PDF(取前3页)with open('源.pdf', 'rb') as f: reader = PyPDF2.PdfReader(f) writer = PyPDF2.PdfWriter()for i in range(3): writer.add_page(reader.pages[i]) with open('前3页.pdf', 'wb') as out: writer.write(out)# 加水印(需要提前准备水印PDF)with open('源.pdf', 'rb') as src, open('水印.pdf', 'rb') as wm: reader = PyPDF2.PdfReader(src) watermark = PyPDF2.PdfReader(wm).pages[0] writer = PyPDF2.PdfWriter()for page in reader.pages: page.merge_page(watermark) writer.add_page(page) with open('带水印.pdf', 'wb') as out: writer.write(out)PdfMerger().append():把PDF文件加入合并列表。PdfReader:读取PDF,.pages 是所有页的列表。PdfWriter:创建新PDF,用 .add_page() 添加页。page.merge_page(watermark):把水印页叠加到当前页。PdfMerger的append不会一次性读入所有文件,可以放心。with open(... as f)确保文件正确关闭。import smtplibfrom email.mime.multipart import MIMEMultipartfrom email.mime.text import MIMETextfrom email.mime.base import MIMEBasefrom email import encoders# 设置邮箱信息发件人 = '你的邮箱@qq.com'密码 = '授权码'# 不是登录密码收件人 = '领导@公司.com'# 构造邮件msg = MIMEMultipart()msg['From'] = 发件人msg['To'] = 收件人msg['Subject'] = '成绩报告'正文 = MIMEText('领导好,请查收附件。', 'plain', 'utf-8')msg.attach(正文)# 添加附件with open('报告.pdf', 'rb') as f: part = MIMEBase('application', 'octet-stream') part.set_payload(f.read()) encoders.encode_base64(part) part.add_header('Content-Disposition', 'attachment; filename=报告.pdf') msg.attach(part)# 发送server = smtplib.SMTP_SSL('smtp.qq.com', 465)server.login(发件人, 密码)server.send_message(msg)server.quit()MIMEMultipart():创建一个可包含正文和附件的邮件对象。MIMEText():创建纯文本正文。MIMEBase + encoders.encode_base64:将文件转成附件格式。add_header:设置附件的文件名。SMTP_SSL:连接QQ邮箱的SSL服务器,登录,发送。email.utils.encode_header处理。time.sleep(1)间隔。from PIL import Image, ImageDraw, ImageFontimport os# 批量缩放for f in os.listdir('照片'):if not f.endswith('.jpg'): continue img = Image.open(os.path.join('照片', f)) img.thumbnail((800, 600)) # 等比例缩放到不超过800x600 img.save(os.path.join('处理后', f))# 添加文字水印img = Image.open('照片.jpg').convert('RGBA')txt = Image.new('RGBA', img.size, (255,255,255,0))draw = ImageDraw.Draw(txt)font = ImageFont.truetype('simhei.ttf', 40)draw.text((100,100), '保密', fill=(255,255,255,128), font=font)out = Image.alpha_composite(img, txt)out.convert('RGB').save('带水印.jpg')Image.open():打开图片。.thumbnail((宽,高)):等比例缩放,不会变形。convert('RGBA'):转成带透明通道的模式,方便叠加水印。Image.new('RGBA', size, 颜色):创建一张透明图片。ImageDraw.Draw():在图片上画画。ImageFont.truetype():加载中文字体。draw.text():写字,fill 最后一个参数是透明度(0-255)。Image.alpha_composite():叠加两张透明图。convert('RGBA'),合并后再转回RGB保存。simhei.ttf,Mac用 'PingFang.ttc'。import matplotlib.pyplot as plt# 解决中文乱码plt.rcParams['font.sans-serif'] = ['SimHei']plt.rcParams['axes.unicode_minus'] = False# 折线图plt.plot(['1月','2月','3月'], [85,90,88], marker='o')plt.title('成绩趋势')plt.grid(True)plt.show()# 柱状图plt.bar(['三(1)','三(2)'], [92,88])plt.title('班级对比')for i, v in enumerate([92,88]): plt.text(i, v+1, str(v), ha='center')plt.show()# 饼图plt.pie([45,30,25], labels=['教学','科研','行政'], autopct='%1.1f%%')plt.axis('equal')plt.show()# 保存图片plt.savefig('图表.png', dpi=300, bbox_inches='tight')plt.rcParams:设置全局字体,解决中文乱码。plt.plot():画折线图,marker 是点的样式。plt.bar():画柱状图。plt.text():在指定坐标加文字,用于显示柱子上的数值。plt.pie():画饼图,autopct 显示百分比格式。plt.axis('equal'):让饼图是正圆。plt.savefig():保存图片,dpi分辨率,bbox_inches='tight'去除白边。plt.show()之后不能保存,因为画布被清空。要先savefig再show。axis('equal') 会变成椭圆,很难看。# 字符串拼接name = '张三'age = 25print('我叫' + name + ',今年' + str(age) + '岁') # 数字要转字符串print(f'我叫{name},今年{age}岁') # 推荐 f-string# 列表操作fruits = ['苹果','香蕉']fruits.append('橘子') # 末尾加fruits.insert(1, '草莓') # 指定位置加if'香蕉'in fruits: # 先判断再删除 fruits.remove('香蕉')# 字典操作student = {'姓名':'张三', '年龄':12}print(student['姓名']) # 键不存在会报错print(student.get('性别', '未知')) # 安全访问# 文件读写with open('笔记.txt', 'w', encoding='utf-8') as f: f.write('hello')with open('笔记.txt', 'r', encoding='utf-8') as f: content = f.read()open 不指定 encoding,中文可能乱码,特别是Windows。[]访问不存在的键直接报错,用 get 更安全。in 判断一下,否则会报 ValueError。[f for f in os.listdir('.') if os.path.isfile(f)] | |
shutil.move('旧','新') | |
pd.read_excel('文件.xlsx') | |
pd.read_csv('文件.csv', encoding='utf-8-sig') | |
df.head()df.info()、df.describe() | |
df.dropna() | |
df.fillna(0) | |
df[df['列'] > 90] | |
df[(条件1) & (条件2)] | |
df['新列'] = 计算 | |
df.groupby('列')['值'].mean() | |
pd.concat([df1,df2]) | |
df.to_excel('文件.xlsx', index=False) | |
doc = DocxTemplate('模板.docx')doc.render({...}) | |
PyPDF2.PdfMerger().append('1.pdf').write('合并.pdf') | |
smtplib.SMTP_SSL().login().send_message() | |
Image.open().thumbnail((800,600)).save() | |
plt.plot(x,y) | |
plt.bar(x,y) | |
plt.savefig('图.png') |
把你家里或者办公室里最乱的一个文件夹,用今天复习的代码整理一下:
做完你会发现:原来Python真的能省好多时间。
Excel处理几十万行数据卡成狗怎么办?下期我们正式进入数据库,用SQLite存储所有成绩数据,查询分析快到飞起。记得来哈。
回复「Py-Day」获取相关学习资料及源码
Day29:Matplotlib数据可视化速查手册—从画图到出报告,这些坑我都替你踩过了
Day28:Pandas数据处理速查手册(二)从Excel到数据分析,这些坑我都替你踩过了
Day27:Python基础语法速查手册(一)从变量到函数,这些坑我都替你踩过了
Day20:批量文件终结者!用Python一键处理100个Excel,自动生成汇总报表