在 Python 中使用 7zip 备份文件的操作


Posted in Python onDecember 11, 2020

我在按照 Byte of python一步步的学习Python, 在学到‘解决方案'的时候,原文的实例 “backup_ver1.py” 是用zip备份文件。

这里面我有几点不一样的地方:

我的电脑没有zip,我用的是7zip;

原文直接用‘zip'命令备份,我直接使用7z命令报错。

使用7z命令备份之前,需要把7zip的安装目录添加到系统环境变量Path中;这时候我可以在CMD中执行7z,但是在python中还是报错,“7z is not recognized as an internal ……”

下面三种方法可以在python中正确运行7z命令:

# 方法1: 拷贝 7z.exe 和7z.dll 到当前python文件所在的目录下。 否则,不认识7z 命令。

zip_command = '7z a -tzip {0} {1} -r'.format(target, ' '.join(source))

# 方法2: os.system() 里面执行的是同目录下的exe, 使用如下os.chdir() 命令切换 path。

os.chdir('D:\\Program Files (x86)\\7-Zip')
print('切换当前路径为:', os.getcwd())
zip_command = '7z a -tzip {0} {1} -r'.format(target, ' '.join(source))

# 方法3:在cmd 命令中写入7z.exe所在的目录

zip_command = '"D:\\Program Files (x86)\\7-Zip\\7z.exe" a -tzip {0} {1} '.format(target, ' '.join(source))

import os
import time
 
# 1. 需要备份的文件与目录将被指定在一个列表中。
# 例如在 Windows 下:source = ['"C:\\My Documents"', 'C:\\Code']
# 又例如在 Mac OS X 与 Linux 下:source = ['/Users/swa/notes']
source = ['D:\\test\\fold\\']
# 在这里要注意到我们必须在字符串中使用双引号用以括起其中包含空格的名称。
 
# 2. 备份文件必须存储在一个主备份目录中
# 例如在 Windows 下:target_dir = 'E:\\Backup'
# 又例如在 Mac OS X 和 Linux 下:target_dir = '/Users/swa/backup'
target_dir = 'D:\\test\\Backup'
# 要记得将这里的目录地址修改至你将使用的路径
 
# 3. 备份文件将打包压缩成 zip 文件。
# 4. zip 压缩文件的文件名由当前日期与时间构成。
# os.sep 变量的使用方式——它将根据你的操作系统给出相应的分隔符,在# GNU/Linux 与 Unix 中它会是 '/' ,在 Windows 中它会是 '\\' ,在 Mac OS 中它会是 ':'
target = target_dir + os.sep + time.strftime('%Y%m%d%H%M%S') + '.zip'
 
# 如果目标目录还不存在,则进行创建
if not os.path.exists(target_dir):
 os.mkdir(target_dir)
 
# 5. 我们使用 zip 命令将文件打包成 zip 格式
# 方法1: 拷贝 7z.exe 和7z.dll 到当前python文件所在的目录下。 否则,不认识7z 命令。
# zip_command = '7z a -tzip {0} {1} -r'.format(target, ' '.join(source))
 
# 方法2: os.system() 里面执行的是同目录下的exe, 使用如下os.chdir() 命令切换 path。
# os.chdir('D:\\Program Files (x86)\\7-Zip')
# print('切换当前路径为:', os.getcwd())
# zip_command = '7z a -tzip {0} {1} -r'.format(target, ' '.join(source))
 
# 方法3:在cmd 命令中写入7z.exe所在的目录
# -mcu 强制使用utf-8 编码文件名
zip_command = '"D:\\Program Files (x86)\\7-Zip\\7z.exe" a -tzip -mcu {0} {1} '.format(target, ' '.join(source))
# 运行备份
print('\nZip command is:')
print(zip_command)
print('Running:') 
 
if os.system(zip_command) == 0:
 print('Successful backup to', target)
else:
 print('Backup FAILED')
 
# 查看压缩文件内容
check_command = '"D:\\Program Files (x86)\\7-Zip\\7z.exe" l {0}'.format(target)
 
print('\nCheck zipfile command is:')
print(check_command)
print('Running:')
 
# 使用 os.system(check_command) 中文返回有乱码,所以使用 os.popen
# if os.system(check_command) == 0:
# print('Please check the file list in:', target)
# else:
# print('Check info FAILED')
print('Please check the file list in:', target)
p = os.popen(check_command)
print(p.read())
p.close()
 
 
# 解压缩到目录
extr_command = '"D:\\Program Files (x86)\\7-Zip\\7z.exe" x {0} -oD:\\test\\extract\\ -y'.format(target)
 
print('\nExtract command is:')
print(extr_command)
print('Running:')
 
if os.system(extr_command) == 0:
 print('Successful extract to', 'D:\\test\\extract')
else:
 print('Extract FAILED')

注意:

在压缩的时候,不要使用 -r,递归会把folder同级的其它目录下的文件一起压缩;

在解压的时候,使用-y,如果当前目录下已存在被解压的目录和文件,替换目标文件。

zip_command = '"D:\\Program Files (x86)\\7-Zip\\7z.exe" a -tzip {0} {1} -r'.format(target, ' '.join(source))

extr_command = '"D:\\Program Files (x86)\\7-Zip\\7z.exe" x {0} -oD:\\test\\extract\\ -y'.format(target)

补充知识:谁说Python的shutil不支持7z解压缩,我来教你扩展它的功能!

python的内置模块

在Python的标准库中,有哪些你常用并且觉得犀利无比的模块?不要说time、datetime、os、sys。这些模块常用是常用,但是逼格不够高啊。举个例子,如果你经常在LeetCode上刷题,你会发现有时Java、C需要几十行的算法题,如果Python使用了collections、itertools,可能三四行代码就结束了。

shutil的便利

日常的编码中,常会涉及到对文件、目录等的操作场景,如果我们使用os,可能需要对文件、文件夹,非空等进行逐个判断。举个例子: 我们现在要删除一个目录,目录中包含有文件与文件夹,如果使用os模块,没有现成可以使用的函数,需要我们进行判断与分类执行。

import os
# path是文件的路径,如果这个路径是一个文件夹,
# 则会抛出OSError的错误,这时需用用rmdir()来删除
os.remove(path)
# path是文件夹路径,注意文件夹需空的才能被删除
os.rmdir(path)

多数初学者遇到删除文件夹,想到的操作就是,创建两个列表,然后用os.walk遍历目录,将文件与文件夹分别存入初始化的两个列表中,然后先统一删除文件,最后删除文件夹。如果有上面这样操作的同学,请面壁三分钟。明显没有好好学习os.walk函数。

os.walk(top[, topdown=True[, οnerrοr=None[, followlinks=False]]]) top -- 是你所要遍历的目录的地址, 返回的是一个三元组(root,dirs,files)。

root 所指的是当前正在遍历的这个文件夹的本身的地址

dirs 是一个 list ,内容是该文件夹中所有的目录的名字(不包括子目录)

files 同样是 list , 内容是该文件夹中所有的文件(不包括子目录)

topdown --可选,为 True,则优先遍历 top 目录,否则优先遍历 top 的子目录(默认为开启)。如果 topdown 参数为 True,walk 会遍历top文件夹,与top 文件夹中每一个子目录。

onerror -- 可选,需要一个 callable 对象,当 walk 需要异常时,会调用。

followlinks -- 可选,如果为 True,则会遍历目录下的快捷方式(linux 下是软连接 symbolic link )实际所指的目录(默认关闭),如果为 False,则优先遍历 top 的子目录。

只需要将topdown设置为False,这样在遍历目录时,就会从根节点进行遍历,然后我们逐个删除就ok了,哪里需要那么麻烦!代码如下:

import os 
for root, dirs, files in os.walk('D:\\software_temp', topdown=False):
 for name in files:
 os.remove(os.path.join(root, name))
 for name in dirs:
 os.rmdir(os.path.join(root, name))

说这么多,无外乎为了引出最简便的方式 : shutil模块

如果换做shutil模块登场,那么执行删除目录的操作,只需要0.1秒的时间:

import shutil

shutil.rmtree('D:\\software_temp')

就这样,完事儿了...

文件解压缩

日常工作中,我们经常会使用python进行文件的解压缩处理。python自带的解压缩模块有zipfile, gzip, tarfile,如果我们需要解压rar文件则需要单独下载rarfile模块,针对每一种压缩文件,我们都需要针对文件类型进行对应模块的使用,是不是很繁琐?如果我们使用shutil呢?让我们先来看看shutil支持的解压类型:

import pprint
import shutil
pprint.pprint(shutil.get_unpack_formats())
 
output:
[('bztar', ['.tar.bz2', '.tbz2'], "bzip2'ed tar-file"),
 ('gztar', ['.tar.gz', '.tgz'], "gzip'ed tar-file"),
 ('tar', ['.tar'], 'uncompressed tar file'),
 ('xztar', ['.tar.xz', '.txz'], "xz'ed tar-file"),
 ('zip', ['.zip'], 'ZIP file')]

shutil已经包含了我们上面提到的所有文件。

.7z文件是什么鬼?

众所周知,zip的压缩率相比rar是比较低的,但是商业软件下载中,你很少会见到.rar的文件,why?因为专利啊...

RAR是一种专利文件格式,用于数据压缩与归档打包,开发者为尤金·罗谢尔(俄语:Евгений Лазаревич Рошал,拉丁转写:Yevgeny Lazarevich Roshal),RAR的全名是“Roshal ARchive”,即“罗谢尔的归档”之意。首个公开版本RAR 1.3发布于1993年。

所以,有很多产品在软件发布时,开始使用一种压缩率更高的.7z文件,这又是为什么?来让我们访问一下7-zip的官网:7-zip官方主页:https://sparanoid.com/lab/7z/在其中有一个许可协议是这样写的

许可协议:

7-Zip 是一款 开源 软件。大多数源代码都基于 GNU LGPL 许可协议下发布。AES 代码基于 BSD 许可下发布。unRAR 代码基于两种许可:GNU LGPL 和 unRAR 限制许可。更多下许可信息请查看:7-Zip 许可。您可以在任何一台计算机上使用 7-Zip ,包括用在商业用途的计算机,不对 7-Zip 进行捐赠或支付并不影响您的使用。

shutil扩展7z

说了这么多7z文件的好处,可我们看到shutil并不能解压该类型的文件啊。我们能否让shutil支持.7z文件,达到无脑解压缩呢?此时,你需要py7zr模块。养成好习惯,遇到模块先找GitHub:https://github.com/miurahr/py7zr

1. 模块下载

pip install py7zr

2. 基本使用

当我们安装好py7zr后,它可以在cmd下直接运行该命令

List archive contents
$ py7zr l test.7z
Extract archive
$ py7zr x test.7z
Extract archive with password
$ py7zr x -P test.7z
 password?: ****
Create and compress to archive
$ py7zr c target.7z test_dir
Create multi-volume archive
$ py7zr c -v 500k target.7z test_dir
Test archive
$ py7zr t test.7z
Show information
$ py7zr i
Show version
$ py7zr --version

单独使用模块

import py7zr
 
archive = py7zr.SevenZipFile('sample.7z', mode='r')
archive.extractall(path="/tmp")
archive.close()
 
with py7zr.SevenZipFile('target.7z', 'w') as z:
 z.writeall('./base_dir')

3. shutil集成

之所以推荐py7zr给大家,不仅因为他的简单好用,更是由于他可以轻松集成于shutil,来看看它的使用方式吧:

from py7zr import pack_7zarchvie, unpack_7zarchive
import shutil
 
# register file format at first.
shutil.register_archive_format('7zip',
    pack_7zarchive,
    description='7zip archive')
 
shutil.register_unpack_format('7zip',
    ['.7z'],
    unpack_7zarchive,
    description='7zip archive')
 
# extraction
shutil.unpack_archive('test.7z', '/tmp')
 
# compression
shutil.make_archive('target', '7zip', 'src')
 
pprint.pprint(shutil.get_unpack_formats())
 
# output:
[('7zip', ['.7z'], '7zip archive'),
 ('bztar', ['.tar.bz2', '.tbz2'], "bzip2'ed tar-file"),
 ('gztar', ['.tar.gz', '.tgz'], "gzip'ed tar-file"),
 ('tar', ['.tar'], 'uncompressed tar file'),
 ('xztar', ['.tar.xz', '.txz'], "xz'ed tar-file"),
 ('zip', ['.zip'], 'ZIP file')]

通过注册我们看到,shutil已经支持7z文件的解压了,就是如此简单。

以上为个人经验,希望能给大家一个参考,也希望大家多多支持三水点靠木。如有错误或未考虑完全的地方欢迎留言讨论,望不吝赐教。

Python 相关文章推荐
Python查询阿里巴巴关键字排名的方法
Jul 08 Python
Python数组遍历的简单实现方法小结
Apr 27 Python
Sanic框架安装与简单入门示例
Jul 16 Python
对python中矩阵相加函数sum()的使用详解
Jan 28 Python
Python里字典的基本用法(包括嵌套字典)
Feb 27 Python
Python 实现一个手机号码获取妹子名字的功能
Sep 25 Python
python pycharm的安装及其使用
Oct 11 Python
python 协程中的迭代器,生成器原理及应用实例详解
Oct 28 Python
对Keras中predict()方法和predict_classes()方法的区别说明
Jun 09 Python
Django自带用户认证系统使用方法解析
Nov 12 Python
举例讲解Python装饰器
Dec 24 Python
Pytorch反向传播中的细节-计算梯度时的默认累加操作
Jun 05 Python
Python文件名匹配与文件复制的实现
Dec 11 #Python
Python: glob匹配文件的操作
Dec 11 #Python
Python Socket多线程并发原理及实现
Dec 11 #Python
python 实现Harris角点检测算法
Dec 11 #Python
使用python画出逻辑斯蒂映射(logistic map)中的分叉图案例
Dec 11 #Python
Python3 用matplotlib绘制sigmoid函数的案例
Dec 11 #Python
python 基于opencv 实现一个鼠标绘图小程序
Dec 11 #Python
You might like
PHP中一个控制字符串输出的函数
2006/10/09 PHP
php采集速度探究总结(原创)
2008/04/18 PHP
追求程序速度,而不是编程的速度
2008/04/23 PHP
php设计模式 Strategy(策略模式)
2011/06/26 PHP
php中通过数组进行高效随机抽取指定条记录的算法
2013/09/09 PHP
PHP中substr()与explode()函数用法分析
2014/11/24 PHP
Javascript根据指定下标或对象删除数组元素
2012/12/21 Javascript
封装好的js判断操作系统与浏览器代码分享
2015/01/09 Javascript
浅析JavaScript Array和string的转换(推荐)
2016/05/20 Javascript
JavaScript基于对象去除数组重复项的方法
2016/10/09 Javascript
微信小程序之拖拽排序(代码分享)
2017/01/21 Javascript
简单实现jquery隔行变色
2017/11/09 jQuery
React从react-router路由上做登陆验证控制的方法
2018/05/10 Javascript
Javascript实现异步编程的过程
2018/06/18 Javascript
vue使用swiper实现左右滑动切换图片
2020/10/16 Javascript
详解JavaScript原型与原型链
2020/11/16 Javascript
Python设置默认编码为utf8的方法
2016/07/01 Python
python基础_文件操作实现全文或单行替换的方法
2017/09/04 Python
Python排序搜索基本算法之插入排序实例分析
2017/12/11 Python
python pygame模块编写飞机大战
2018/11/20 Python
python 调用有道api接口的方法
2019/01/03 Python
python 利用jinja2模板生成html代码实例
2019/10/10 Python
在Django中实现添加user到group并查看
2019/11/18 Python
python如何实现单链表的反转
2020/02/10 Python
Python中的Cookie模块如何使用
2020/06/04 Python
HTML5新增的表单元素和属性实例解析
2014/07/07 HTML / CSS
新西兰演唱会和体育门票网站:Ticketmaster新西兰
2017/10/07 全球购物
德国大型箱包和皮具商店:Koffer
2019/10/01 全球购物
英国办公家具网站:Furniture At Work
2019/10/07 全球购物
学前教育专业毕业生自荐信
2013/10/03 职场文书
表扬信格式
2014/01/12 职场文书
四风剖析查摆对照检查材料思想汇报
2014/09/24 职场文书
代办社保委托书范文
2014/10/06 职场文书
2016新春团拜会致辞
2015/08/01 职场文书
python爬虫selenium模块详解
2021/03/30 Python
处理canvas绘制图片模糊问题
2022/05/11 Javascript