在 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中urllib+urllib2+cookielib模块编写爬虫实战
Jan 20 Python
Phantomjs抓取渲染JS后的网页(Python代码)
May 13 Python
用python记录运行pid,并在需要时kill掉它们的实例
Jan 16 Python
值得收藏,Python 开发中的高级技巧
Nov 23 Python
python实现几种归一化方法(Normalization Method)
Jul 31 Python
Pytorch根据layers的name冻结训练方式
Jan 06 Python
关于Tensorflow 模型持久化详解
Feb 12 Python
Python Opencv 通过轨迹(跟踪)栏实现更改整张图像的背景颜色
Mar 09 Python
解决Keras的自定义lambda层去reshape张量时model保存出错问题
Jul 01 Python
python调用私有属性的方法总结
Jul 24 Python
python中pow函数用法及功能说明
Dec 04 Python
python opencv图像处理(素描、怀旧、光照、流年、滤镜 原理及实现)
Dec 10 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反弹shell实现代码
2009/04/22 PHP
php 获取一个月第一天与最后一天的代码
2010/05/16 PHP
PHP OPCode缓存 APC详细介绍
2010/10/12 PHP
PHP+MySQL统计该库中每个表的记录数并按递减顺序排列的方法
2016/02/15 PHP
PHP数组生成XML格式数据的封装类实例
2016/11/10 PHP
laravel-admin解决表单select联动时,编辑默认没选上的问题
2019/09/30 PHP
PHP vsprintf()函数格式化字符串操作原理解析
2020/07/14 PHP
js 数组实现一个类似ruby的迭代器
2009/10/27 Javascript
jQuery实现复选框全选/取消全选/反选及获得选择的值
2014/06/12 Javascript
从数据库读取数据后将其输出成html标签的三种方法
2014/10/13 Javascript
Js遍历键值对形式对象或Map形式的方法
2016/08/08 Javascript
浅谈jQuery为哪般去掉了浏览器检测
2016/08/29 Javascript
AngularJS实现ajax请求的方法
2016/11/22 Javascript
浅谈js for循环输出i为同一值的问题
2017/03/01 Javascript
JavaScript观察者模式(publish/subscribe)原理与实现方法
2017/03/30 Javascript
vue2.0实现分页组件的实例代码
2017/06/22 Javascript
jQuery实现手机号正则验证输入及自动填充空格功能
2018/01/02 jQuery
js实现类似iphone的网页滑屏解锁功能示例【附源码下载】
2019/06/10 Javascript
Vue+Koa2 打包后进行线上部署的教程详解
2019/07/31 Javascript
vue分页插件的使用方法
2019/12/25 Javascript
Vue环境搭建+VSCode+Win10的详细教程
2020/08/19 Javascript
Vue 使用typescript如何优雅的调用swagger API
2020/09/01 Javascript
python多线程用法实例详解
2015/01/15 Python
给Python入门者的一些编程建议
2015/06/15 Python
Python如何为图片添加水印
2016/11/25 Python
Python运算符重载详解及实例代码
2017/03/07 Python
详解python爬取弹幕与数据分析
2020/11/14 Python
SAZAC的动物连体衣和动物睡衣:Kigurumi Shop
2020/03/14 全球购物
咨询公司各岗位职责
2013/12/02 职场文书
大学生简历的个人自我评价
2013/12/04 职场文书
奥巴马竞选演讲稿
2014/05/15 职场文书
户籍证明书标准模板
2014/09/10 职场文书
2014年国庆节演讲稿
2014/09/19 职场文书
2015年暑假工作总结
2015/07/13 职场文书
财务管理制度范本
2015/08/04 职场文书
为Java项目添加Redis缓存的方法
2021/05/18 Redis