目录
- 1.读取
- 1.1 获取压缩包内文件列表
- 1.2 处理中文编码问题
- 1.3 读取压缩包内文件信息
- 2.解压
- 2.1 单个文件
- 2.2 压缩包含中文名文件
- 2.3 所有文件
- 2.4 设密码的压缩包
- 3.压缩
- 3.1 创建压缩包
- 3.2 向压缩包添加文件
- 4.实战: 文件压缩备份
- 4.1 学习版
- 4.2 衍生: 通用版
- 5.拓展知识
- 5.1 time.strptime()
- 5.2 time.mktime()
1.读取
1.1 获取压缩包内文件列表
zipfile.ZipFile(),namelist()
import zipfile
with zipfile.ZipFile('backup.zip', 'r') as zipobj:
print(zipobj.namelist())
1.2 处理中文编码问题
import zipfile
with zipfile.ZipFile('backup.zip', 'r') as zipobj:
for file_name in zipobj.namelist():
print(file_name.encode('cp437').decode('gbk'))
1.3 读取压缩包内文件信息
zipobj.getinfo()
import zipfile
with zipfile.ZipFile('backup.zip', 'r') as zipobj:
for file_name in zipobj.namelist():
info = zipobj.getinfo(file_name)
file_name = file_name.encode('cp437').decode('gbk')
print(file_name, info.file_size, info.compress_size)
.file_size为文件原始大小
.compress_size为文件压缩后大小
两者单位均为字节
2.解压
2.1 单个文件
import zipfile
with zipfile.ZipFile('backup.zip', 'r') as zipobj:
zipobj.extract('2020-03-29-1.zip', 'picture')
不指定path时,解压到同目录下
2.2 压缩包含中文名文件
注意:解压时需要获取其乱码的名字进行解压后再重命名
import os, zipfile
with zipfile.ZipFile('backup.zip', 'r') as zipobj:
for file in zipobj.namelist():
zipobj.extract(file)
# 更改编码,获取中文文件名
file_chinese = file.encode('cp437').decode('gbk')
# 重命名
os.rename(file, file_chinese)
建议:少使用中文命名文件及文件夹
2.3 所有文件
import zipfile
with zipfile.ZipFile('backup.zip', 'r') as zipobj:
zipobj.extractall(path='picture')
path为你所需要解压到的路径,如不存在则会自动创建
2.4 设密码的压缩包
import zipfile
with zipfile.ZipFile('backup.zip', 'r') as zipobj:
zipobj.extractall(path='picture', pwd=b'123456')
pwd为压缩包密码,b将字符串转换,效果等同.encode(‘ascii’)
3.压缩
3.1 创建压缩包
zipobj.write()
import zipfile
file_list = ['pie.xlsx', 'test.xlsx']
with zipfile.ZipFile('backup.zip', 'w') as zipobj:
for file in file_list:
zipobj.write(file)
如果压缩文件包已存在,直接替换原压缩文件
3.2 向压缩包添加文件
import zipfile
with zipfile.ZipFile('backup.zip', 'a') as zipobj:
zipobj.write('test1.xlsx')
注意:与创建的差别在于zipfile.ZipFile()第二个参数是a还是w
4.实战: 文件压缩备份
要求:
1.找出当前目录下所有距离上次修改时间超过3个月的文件
2.将所有文件重命名,在原本文件名的开头加上最后修改日期
3.创建一个新的文件夹backup
4.将所有重命名后的文件都添加到压缩包里,给压缩包命名为创建日期
5.将压缩包移动到backup文件夹
6.删除原始文件
4.1 学习版
import os, zipfile, shutil
import time, datetime, arrow
# 检查并创建文件夹
if not os.path.exists('backup'):
os.mkdir('backup')
# 获取当前时间并转换为字符串
nowtime = str(datetime.datetime.fromtimestamp(time.time()))
# 时间限制(月份)
ct_time = 3
# 遍历当前目录文件
for file in os.scandir():
# 判断是否为文件
if file.is_file():
# 获取文件创建时间
file_mtime = os.stat(file).st_mtime
# 当前时间减去创建时间获得的时间戳和限制时间(月份)转换为秒浮点数对比
if file_mtime < arrow.now().shift(months=-ct_time).timestamp:
# 转换创建时间格式并获取与原文件名组合为新文件名
file_newname = str(datetime.datetime.fromtimestamp(file_mtime))[0:10] + '-' + file.name
# 复制创建时间超过限制时间的文件并重命名
shutil.copy(file.name, file_newname)
# 判断压缩包是否存在,没有赋值参数w,有则赋值a给zip_mode
zip_mode = 'w' if not os.path.exists(nowtime[0:10] + '.zip') else 'a'
# 通过zip_mode的值进行创建压缩包或添加文件到压缩包
with zipfile.ZipFile(nowtime[0:10] + '.zip', zip_mode) as zipobj:
zipobj.write(file_newname)
# 移除复制的文件
os.remove(file_newname)
# 将备份文件压缩包移动到backup文件夹
shutil.move(nowtime[0:10]+ '.zip', 'backup/')
说明:为了保存我当前目录超过三个月的文件不被打包,我使用了shutil.copy进行复制重命名,按实际对旧文件进行打包备份的话,应该用os.rename()
4.2 衍生: 通用版
import zipfile, os, shutil, time, datetime, fnmatch, arrow
# 限制时间判断
def time_float(limit_time, file_mtime):
# 不限时间
if limit_time == '':
return True
# 输入几个月前:1-12
elif len(limit_time) < 3 and int(limit_time) <= 12:
# 通过arrow模块shift函数获取前几月时间迭代器,timestamp获取时间戳与文件创建时间比较
if file_mtime < arrow.now().shift(months=-int(limit_time)).timestamp:
return True
else:
return False
# 输入时间节点2020-01-31
else:
limit_time = time.mktime(time.strptime(limit_time, "%Y-%m-%d"))
# 文件创建时间和时间节点比较
if file_mtime < limit_time:
return True
else:
return False
# 文件备份压缩
def back_zip(back_path, back_name, sort, limit_time, find_path):
# 检查并创建文件夹
if not os.path.exists(back_path):
os.mkdir(back_path)
# 获取当前时间并转换为字符串2020-04-13,并和back_name组合为压缩包名字
zip_name = str(datetime.datetime.fromtimestamp(time.time()))[0:10]+'-'+back_name+'.zip'
# 遍历当前目录文件
for dirpath, dirnames, files in os.walk(find_path):
# 跳过备份路径
if not dirpath == back_path:
# 改变工作路径到当前遍历文件夹
os.chdir(dirpath)
for file in files:
if fnmatch.fnmatch(file, '*.'+sort):
# 获取文件创建时间
file_mtime = os.stat(file).st_mtime
# 调用时间判断
if time_float(limit_time, file_mtime):
# 转换创建时间格式并获取与原文件名组合为新文件名
new_name = str(datetime.datetime.fromtimestamp(file_mtime))[0:10] + '-' + file
# 复制创建时间超过限制时间的文件并重命名
shutil.copy(file, new_name)
# 存储压缩包是否存在同文件的判断结果
result = True
# 判断压缩包是否存在,没有赋值参数w,有则赋值a给zip_mode
zip_mode = 'w' if not os.path.exists(os.path.join(find_path, zip_name)) else 'a'
if zip_mode == 'a':
with zipfile.ZipFile(os.path.join(find_path, zip_name),'r') as zipobj:
# 遍历压缩包文件
for filename in zipobj.namelist():
# 判断是否存在同文件
if new_name == filename:
result = False
break
result = True
# print(result)
# 不存在同文件则添加压缩
if not result == False:
# 通过zip_mode的值进行创建压缩包或添加文件到压缩包
with zipfile.ZipFile(os.path.join(find_path, zip_name), zip_mode) as zipobj:
zipobj.write(new_name)
# 移除复制的文件
os.remove(new_name)
# 改变工作路径到压缩包路径
os.chdir(find_path)
# 将备份文件压缩包移动到backup文件夹
shutil.move(zip_name, back_path)
if __name__ == "__main__":
back_path = input("备份路径:")
back_name = input("备份名字:")
sort = input("备份类型:")
limit_time = input("时间限制:")
find_path = input("查找路径:")
back_zip(back_path, back_name, sort, limit_time, find_path)
说明:该通用版将遍历目录、备份路径均设为通过输入确认目标,备份类型可指定某类型(例如:jpg)也可以全部(输入:*),时间限制单独写了一个函数,分三种情况,不做时间限制直接回车、对超过N月的输入(1-12)、对某时间节点之前的输入(2020-4-14),备份名字是便于在同一天备份区分所设。
PS:在逻辑和写法上还有很多进步空间,随知识的积累,再进一步优化提高。
Bug1:记录一个小小的bug,在时间判断中,学习版和通用版都有小小的缺陷,在时间转换为浮点数时均以每个月30天计算,存在一两天的误差,待下一步修补。(已修改,利用arrow模块)
Bug2:新发现遍历遇到同样名字的文件,并且创建时间相同,报错。解决思路:筛选匹配,不存在则压缩。(已修改)
5.拓展知识
5.1 time.strptime()
根据指定的格式把一个时间字符串解析为时间元组
import time
test = "1970-04-01"
struct_time = time.strptime(test, "%Y-%m-%d")
print(struct_time)
输出:time.struct_time(tm_year=1970, tm_mon=4, tm_mday=1, tm_hour=0, tm_min=0, tm_sec=0, tm_wday=2, tm_yday=91, tm_isdst=-1),即时间元组
注意:输入字符串和格式参数相对才可正确转换,格式参数在第二篇time.strftime(“格式”,struct_time)已有详细说明
5.2 time.mktime()
输入struct_time时间元组,返回用秒数来表示时间的浮点数
import time
data = "1970-04-01"
strucr_time = time.strptime(data, "%Y-%m-%d")
t = time.mktime(strucr_time)
print(t) # 输出7747200.0,秒的浮点数
PS:代码均基于Python3.7环境下运行检验,如有不足欢迎评论交流。