Python办公自动化
依赖安装
pip install pandas
pip install openpyxl
文件夹与文件
几个demo
查找 d 盘中 包含 python-office 的文件, 并且格式化输出(并且通过时间时间做出过滤)
import os
import glob
import time
import json
from datetime import datetime
# 查找 d 盘中 包含 python-office 的文件, 并且格式化输出
os.chdir('d:/dee_code')
file_list = glob.glob('**/*python-office*.md', recursive=True)
# 自定义一些时间范围
start_date = datetime(2024, 1, 1)
end_date = datetime(2025, 12, 1)
start_timestamp = time.mktime(start_date.timetuple())
end_timestamp = time.mktime(end_date.timetuple())
# 使用推导式
file_info_list = [
{
'absolute_path': os.path.abspath(f),
'file_size': os.stat(f).st_size / 1024 / 1024,
'create_time': time.strftime('%Y-%m-%d', time.localtime(os.stat(f).st_ctime)),
'modify_time': time.strftime('%Y-%m-%d', time.localtime(os.stat(f).st_mtime))
}
for f in file_list
if start_timestamp <= os.stat(f).st_ctime <= end_timestamp
]
# 打印结果,为了美观和可读性,可以使用 json.dumps 来格式化输出
print(json.dumps(file_info_list, ensure_ascii=False, indent=4))
[
{
"absolute_path": "d:\\dee_code\\dee-blog-code\\source\\_posts\\python-office.md",
"file_size": 0.00748443603515625,
"create_time": "2025-01-02",
"modify_time": "2025-01-04"
}
]
补充说明:列表推导式的用法
# 通用语法
new_list = [expression for item in iterable]
# demo
absolute_file_list = [os.path.abspath(file) for file in list]
# 带条件的列表推导式
even_numbers = [x for x in range(10) if x % 2 == 0]
# 等价传统 for 循环
absolute_file_list = []
for file in list:
absolute_file_list.append(os.path.abspath(file))
查找目标文件夹下空文件和重复文件
import hashlib
import os.path
import json
# 计算文件的 md5 哈希值
def calculate_file_hash(file_path):
hasher = hashlib.md5()
with open(file_path, 'rb') as f:
while chunk := f.read(8192): # 每次读取 8kb 数据块
hasher.update(chunk)
return hasher.hexdigest()
# 查找文件夹中重复文件
def find_repeat_file(path):
if not os.path.isdir(path):
raise Exception('请输入文件夹路径')
file_dic = {} # 存储文件哈希值和对应完整路径
repeat_dic = {} # 存储重复文件的hash值和路径列表
blank_file = []
for dir_path, child_dir_path, file_list in os.walk(path):
# 遍历文件
for file_name in file_list:
# 构建完整路径
file_path = os.path.join(dir_path, file_name)
if os.stat(file_path).st_size == 0:
blank_file.append(file_path)
continue
# 计算文件哈希值
file_hash = calculate_file_hash(file_path)
# 如果文件夹字典中没有, 则添加
if file_hash not in file_dic:
file_dic[file_hash] = file_path
# 否则把重复的文件添加进重复字典
else:
# 先判断字典中有没有该文件
if file_hash not in repeat_dic:
repeat_dic[file_hash] = []
# 将第一次该文件名的首次查询出来的路径放进来
repeat_dic[file_hash].append(file_dic[file_hash])
repeat_dic[file_hash].append(file_path)
json_result = json.dumps(repeat_dic, ensure_ascii=False, indent=4)
print(f'空文件列表 >>> {blank_file}')
print(f'重复文件列表 \n {json_result}')
if __name__ == '__main__':
find_repeat_file(r'D:\Admin\Desktop\test')
基础使用
import pandas as pd
import os
os.chdir(r'D:\Admin\Desktop') # 设置工作路径
data = pd.read_excel('测试.xlsx') # 读取excel文件
dir = os.getcwd() # 获取当前工作路径
print(data)
自动路径连接
import os
p1 = '\外路径'
p2 = '中路径'
p3 = '内路径'
path = os.path.join(p1, p2, p3)
print('c:', path) # c: \外路径\中路径\内路径
遍历文件夹
判断文件和文件夹
list = os.listdir()
file = []
dir = []
for i in list:
if os.path.isdir(i): # 判断文件夹
dir.append(i)
else:
file.append(i)
遍历目录
import os
for 文件 in os.scandir(): # 可以选择文件夹
print(文件.name, 文件.path, 文件.is_dir()) # 文件名 文件路径 是否为文件夹
print(文件.stat()) # 文件属性
# os.stat_result(st_mode=33206, st_ino=0, st_dev=0, st_nlink=0, st_uid=0, st_gid=0, st_size=233, st_atime=1735824570, st_mtime=1735824570, st_ctime=1735822544)
属性说明
名称 | 说明 |
---|---|
st_size | 文件的体积大小(单位:bytes), 除以 1024 就是 KB |
st_atime | 文件的最近访问时间 |
st_mtime | 文件的最近修改时间 |
st_ctime | windws 下创建时间 |
st_birthtime | Mac、linux 下创建时间 |
时间戳转换
import time
import datetime as dt
print('创建时间', time.ctime(1735824570)) # Thu Jan 2 21:29:30 2025
print('创建时间', dt.datetime.fromtimestamp(1735824570)) # 2025-01-02 21:29:30
# 提取具体时间
print(time.year, time.month, time.day, time.hour, time.minute, time.second)
综合查询
import os
import re
dir = []
file = []
# 获取所有文件夹和文件
for i in os.scandir(r'D:\Admin\Downloads'):
if i.is_dir():
dir.append(i.name)
else:
file.append(i.name)
print(f'1)文件夹有{len(dir)}: {dir}')
print(f'2)文件有{len(file)}: {file}')
# 查找所有包含 typora 的文件
typora = []
for i in file:
if 'typora' in i:
typora.append(i)
print(f'3)包含typora的文件有{len(typora)}个: {typora}')
# 查找所有包含 git的文件(不区分大小写)
git = []
reg = '.*git.*'
for i in file:
r = re.match(reg, i, re.I)
try:
git.append(r.group())
except:
pass
print(f'4)包含git的文件有{len(git)}个: {git}')
# 查找所有 excel
excel_list = []
for i in file:
if i.endswith('.xlsx'):
excel_list.append(i)
print(f'excel文件有{len(excel_list)}个: {excel_list}')
👍套娃遍历文件(os.walk()
函数)
import os
count = 0
# 文件夹路径:该目录下所有文件夹全路径, 子文件夹列表:文件夹路径下的所有子文件夹, 文件列表: 文件夹路径下的所有文件
for 文件夹路径, 子文件夹列表, 文件列表 in os.walk(r'D:\Admin\Downloads'):
for i in 文件列表:
print(文件夹路径 + '\\' + i)
count += 1
print(f'找到{count}个文件')
搜索匹配文件名称
字符串内置的方法:startswith()
和 endswith()
glob 模块
glob
是 python 自带的一个文件操作相关模块,用它可以查找符合自己要求的文件,类似于 Windows 下的文件搜索,支持通配符操作,有*
、?
、[]
这三个通配符,
*
:代表0个或者多个字符;
?
:代表一个字符;
[]
:匹配指定范围内的字符,如[0-9]匹配数字;
主要有以下 2 个主要方法。
- glob 方法
- 该方法返回所有匹配的文件路径列表(list)
- 该方法需要一个参数用来制定匹配的路径字符串(字符串可以为绝对路径也可以为相对路径)
- 其返回文件名只包括当前目录里的文件名,不包括子文件夹里的文件
import os
import glob
os.chdir(r'D:\Admin\Desktop')
# print(glob.glob('*.txt'))
# print(glob.glob('test*.txt'))
# print(glob.glob('孙兴华.分析[0-9].*'))
# print(glob.glob('孙兴华.分析[!0-9].*'))
list = glob.glob('*.jpg')
print(list) # 返回一个列表
for f in list:
print(f)
👍👍注意
'''遍历文件夹深层目录下所有的指定文件
'''
import os
import glob
os.chdir(r'D:\Admin\Desktop')
list = glob.glob('**/*.xlsx',recursive=True) # 注意:用**表示任意层文件或文件夹,recursive=True会不断进入文件夹内。查找该路径下面的所有.xlsx文件,包括深层的文件
print(list)
- iglob 方法(选记)
- 获取一个可编历对象,使用它可以逐个获取匹配的文件路径名
- 与
glob.glob()
的区别是:glob.glob
同时获取所有的匹配路径,而glob.iglob
一次只获取一个匹配路径
import os
import glob
os.chdir(r'D:\Admin\Desktop')
list = glob.iglob('*.jpg')
print(list)
for f in list:
print(f)
fnmatch 模块
是否匹配,返回的是 True/False
import os
import fnmatch
# 是否匹配
dir = os.listdir('./')
for f in dir:
if fnmatch.fnmatch(f, '*.txt'): # 匹配规则和 glob 一样
print(f)
创建文件夹
import os
# 创建单层目录
def mkdir(dir):
dir_name = os.path.basename(dir) # 返回路径的最后一个元素
exist = os.path.exists(dir)
if not exist:
os.mkdir(dir)
print(dir_name + "文件夹创建成功")
return True
else:
print('目标已存在: ', dir_name)
def mkdirs(dir):
exist = os.path.exists(dir)
if not exist:
os.makedirs(dir)
print('目录创建成功')
return True
else:
print('目录已存在')
return False
if __name__ == '__main__':
mkdir("./test")
mkdirs('./ss/dd/cc')
操作文件,shutil 模块
判断模块有没有安装
import shutil
#执行会不会报错
import shutil
import os
origin_path = './test.txt'
target_path = './copy/test.txt'
shutil.copy(origin_path, target_path) # 复制文件 注意文件夹要保证存在
shutil.copy2(origin_path, target_path) # 原封不动的复制,包括创建时间和修改时间
origin_dir = './test_dir'
target_dir = './copy/test_dir'
shutil.copytree(origin_dir, target_dir) # 复制文件夹 注意不能是已经存在的文件夹
shutil.move(target_path, origin_path) # 移动文件/文件夹
shutil.rmtree('./ttest.txt') # 删除文件/文件夹
shutil.rename('./test.txt', './test/ttest.txt') # 改名同时进行移动
读写临时文件 TemporaryFile 模块
创建临时文件存储数据
from tempfile import TemporaryFile
with TemporaryFile('w+t') as tmp:
tmp.write('Hello World\n')
tmp.write('Testing\n')
tmp.seek(0)
print(tmp.readlines())
创建临时文件夹存储数据
from tempfile import TemporaryDirectory
# with 表达式 as 变量: 打开文件不用手动关闭, 但要注意缩进
with TemporaryDirectory() as tmpdir:
print(f'临时文件夹是:{tmpdir}')
解压 zip 文件
读取压缩包
import zipfile
# 读取压缩包
with zipfile.ZipFile(r'D:\dee_file\20240805_重庆诉保\hujiao.zip') as f:
for f_name in f.namelist():
f_info = f.getinfo(f_name) # 根据文件名 获取文件信息
print(f_name, f_info) # <ZipInfo filename='hujiao/log/all.log' compress_type=deflate filemode='-rw-rw-rw-' file_size=3878241 compress_size=129218>
解压单个文件
解压全部文件
import zipfile
import os
with zipfile.ZipFile(r'D:\dee_file\20240805_重庆诉保\hujiao.zip', 'r') as file:
print(file)
file.extractall(path=os.getcwd()) # 解压全部 (如果需要密码就额外指定参数 pwd=)
压缩文件
import os
import zipfile
# 压缩文件
def zipDir(dirPath, outFileName=None):
'''
:param dirPath: 目标文件或文件夹
:param outFileName: 压缩文件名,默认和目标文件相同
:return: none
'''
# 如果不校验文件也可以生成zip文件,但是压缩包内容为空,所以最好有限校验路径是否正确
if not os.path.exists(dirPath):
raise Exception("文件路径不存在:", dirPath)
# zip文件名默认和被压缩的文件名相同,文件位置默认在待压缩文件的同级目录
if outFileName == None:
outFileName = dirPath + ".zip"
if not outFileName.endswith("zip"):
raise Exception("压缩文件名的扩展名不正确!因以.zip作为扩展名")
zip = zipfile.ZipFile(outFileName, "w", zipfile.ZIP_DEFLATED)
# 遍历文件或文件夹
for path, dirnames, filenames in os.walk(dirPath):
fpath = path.replace(dirPath, "")
for filename in filenames:
zip.write(os.path.join(path, filename), os.path.join(fpath, filename))
zip.close()
if __name__ == "__main__":
zipDir(r"C:\练习1")
pandas操作Excel
写入
import pandas as pd
import os
path = os.path.join(os.getcwd(), 'test.xlsx')
data = pd.DataFrame({'姓名': ['张三', '李四', '王五'], '年龄': [18, 19, 20]})
data = data.set_index('姓名') # 设置索引列
data.to_excel(path)
print('新建xlsx成功')
读取与修改
读取csv
import os
import pandas as pd
# 新建
path = os.path.join(os.getcwd(), 'tmp.csv')
# data = pd.DataFrame({'姓名': ['张三', '李四', '王五'], '年龄': [18, 19, 20]})
# data = data.set_index('姓名') # 设置索引列
# data.to_csv(path)
# 读取
# data = pd.read_csv(path)
data = pd.read_table(path, sep=',', nrows=3) # 使用read_table()的时候要指定分隔符, 如果有,和\t 要用正则
print(data) # 指定行数
print(data.shape) # 该表有几行几列 (3, 2)
print(data.columns) # 列名 Index(['姓名', '年龄'], dtype='object')
print(data.dtypes) #
读取xlsx
import pandas as pd
path = os.path.join(os.getcwd(), 'tmp.xlsx')
data = pd.readz-excel(path)
# 如果excel没有表头
data = pd.read_excel(path, header=None, names=['序号', '姓名', '年龄'])
# 排序
print(data.sort_values('年龄'))
# 查看是否为空
print(data.isnull())
# 修改
data.to_excel(path)
pandas数据结构
DataFrame:二维数据,整个表格,多行多列 【简称df】
df.index:索引列
df.columns:列名
Series:一维数据,一行或一列
Series
import pandas as pd
# 默认索引列 0,1,2,3
data = pd.Series([520, '张三', 1314, '2024-01-02'])
print(data)
# 指定索引列
data2 = pd.Series(['张三', 18, '2024-01-02'], index=['姓名', '年龄', '日期'])
print(data2)
# 使用python字典创建series
dic = pd.Series({'姓名': '张三', '性别': '男', '年龄': 18})
data3 = pd.Series(dic)
print(data3)
print(f'查询单个索引值 >>> 姓名: {data3['姓名']}') # 查询具体索引的值
print(f'查询多个索引值 >>> 姓名, 性别: {data3[['姓名', '性别']]}') # 查询多个值
DataFrame
DataFrame 的创建
import pandas as pd
data = pd.DataFrame([[1,2,3], [4,5,6], [7,8,9]], columns=['a','b','c'])
print(data)
print(data['a'][0]) # 取a列0行
print(data.loc[0]['a']) # 取a列0行
print(data.iloc[0][0]) # 与列无关, 只取坐标
# 查询多列数据
print(data[['a', 'b']]) # 拿a列和b列
根据字典创建 DataFrame
import pandas as pd
data_dic = {
'姓名': ['张三', '李四', '王五'],
'性别': ['男', '女', '男'],
'年龄': [18, 19, 20]
}
data = pd.DataFrame(data_dic)
print(data)
print(data.dtypes) # 查看列类型
print(data.columns) # 查看列
print(data.index) # 查看索引
print(data['姓名']) # 查看【姓名】列以及对应的值
print(data.loc[1]) # 查看第[1]行数据
print(data.loc[1]['姓名']) # 查看第[1]行的姓名
print(data[['姓名', '年龄']]) # 查看多列以及对应的值
print(data.loc[1:2]) # 查看多行的值
根据多个 series 创建 DataFrame(不常见)
DataFrame 常用方法👍