在上一章中,我们学习了如何处理文件、目录和数据。我们还学习了tarfile
模块。在本章中,我们将学习文件归档、加密和解密。归档在管理文件、目录和数据方面起着重要作用。但首先,什么是归档?归档是将文件和目录存储到单个文件中的过程。Python 有tarfile
模块来创建这样的归档文件。
在本章中,我们将介绍以下主题:
- 创建和解压缩归档文件
- 焦油档案
- ZIP 创建
- 文件加密和解密
在本节中,我们将学习如何使用 Python 的shutil
模块创建和解压缩归档文件。shutil
模块具有make_archive()
功能,创建新的归档文件。使用make_archive()
,我们可以将整个目录及其内容归档。
现在,我们将编写一个名为shutil_make_archive.py
的脚本,并在其中编写以下内容:
import tarfile
import shutil
import sys
shutil.make_archive(
'work_sample', 'gztar',
root_dir='..',
base_dir='work',
)
print('Archive contents:')
with tarfile.open('work_sample.tar.gz', 'r') as t_file:
for names in t_file.getnames():
print(names)
运行该程序,您将获得以下输出:
$ python3 shutil_make_archive.py
Archive contents:
work
work/bye.py
work/shutil_make_archive.py
work/welcome.py
work/hello.py
在前面的示例中,为了创建归档文件,我们使用 Python 的shutil
和tarfile
模块。在shutil.make_archive()
中,我们指定了work_sample
,这将是归档文件的名称,格式为gz
。我们已经在基本目录属性中指定了我们的工作目录名。最后,我们打印了归档文件的名称。
shutil
模块具有unpack_archive()
功能,可以对档案进行解包。使用此功能,我们可以提取归档文件。我们传递了存档文件名和要提取内容的目录。如果没有传递目录名,那么它会将内容提取到当前工作目录中。
现在,创建一个名为shutil_unpack_archive.py
的脚本,并在其中编写以下代码:
import pathlib
import shutil
import sys
import tempfile
with tempfile.TemporaryDirectory() as d:
shutil.unpack_archive('work_sample.tar.gz', extract_dir='/home/student/work',)
prefix_len = len(d) + 1
for extracted in pathlib.Path(d).rglob('*'):
print(str(extracted)[prefix_len:])
按如下方式运行脚本:
student@ubuntu:~/work$ python3 shutil_unpack_archive.py
现在,检查您的work/
目录,您将在其中找到work/
文件夹,其中将包含解压缩的文件。
在本节中,我们将学习tarfile
模块。我们还将学习如何测试输入的文件名,评估它是否是有效的存档文件名。我们将了解如何将新文件添加到已存档的文件中,如何使用tarfile
模块读取元数据,以及如何使用extractall()
函数从存档中提取文件。
首先,我们将测试输入的文件名是否为有效的存档文件。为了测试这一点,tarfile
模块具有is_tarfile()
函数,该函数返回一个布尔值。
创建一个名为check_archive_file.py
的脚本,并在其中写入以下内容:
import tarfile
for f_name in ['hello.py', 'work.tar.gz', 'welcome.py', 'nofile.tar', 'sample.tar.xz']:
try:
print('{:} {}'.format(f_name, tarfile.is_tarfile(f_name)))
except IOError as err:
print('{:} {}'.format(f_name, err))
运行脚本,您将获得以下输出:
student@ubuntu:~/work$ python3 check_archive_file.py
hello.py False
work.tar.gz True
welcome.py False
nofile.tar [Errno 2] No such file or directory: 'nofile.tar'
sample.tar.xz True
因此,tarfile.is_tarfile()
将检查列表中提到的每个文件名。hello.py, welcome.py
文件不是 tar 文件,所以我们得到了一个布尔值,False
。work.tar.gz
和sample.tar.xz
是 tar 文件,所以我们得到了布尔值True
。我们的目录中没有nofile.tar
这样的文件,所以我们得到了一个异常,正如我们在脚本中所写的。
现在,我们将向已经创建的存档文件中添加一个新文件。创建一个名为add_to_archive.py
的脚本,并在其中编写以下代码:
import shutil
import os
import tarfile
print('creating archive')
shutil.make_archive('work', 'tar', root_dir='..', base_dir='work',)
print('\nArchive contents:')
with tarfile.open('work.tar', 'r') as t_file:
for names in t_file.getnames():
print(names)
os.system('touch sample.txt')
print('adding sample.txt')
with tarfile.open('work.tar', mode='a') as t:
t.add('sample.txt')
print('contents:',)
with tarfile.open('work.tar', mode='r') as t:
print([m.name for m in t.getmembers()])
运行脚本,您将获得以下输出:
student@ubuntu:~/work$ python3 add_to_archive.py
Output :
creating archive
Archive contents:
work
work/bye.py
work/shutil_make_archive.py
work/check_archive_file.py
work/welcome.py
work/add_to_archive.py
work/shutil_unpack_archive.py
work/hello.py
adding sample.txt
contents:
['work', 'work/bye.py', 'work/shutil_make_archive.py', 'work/check_archive_file.py', 'work/welcome.py', 'work/add_to_archive.py', 'work/shutil_unpack_archive.py', 'work/hello.py', 'sample.txt']
在本例中,我们首先使用shutil.make_archive()
创建了一个归档文件,然后打印归档文件的内容。然后我们在下一条语句中创建了一个sample.txt
文件。现在,我们想在已经创建的work.tar
中添加sample.txt
。这里,我们使用了追加模式a
。接下来,我们再次显示归档文件的内容。
现在,我们将了解如何从归档文件中读取元数据。getmembers()
函数将加载文件的元数据。创建一个名为read_metadata.py
的脚本,并在其中写入以下内容:
import tarfile
import time
with tarfile.open('work.tar', 'r') as t:
for file_info in t.getmembers():
print(file_info.name)
print("Size :", file_info.size, 'bytes')
print("Type :", file_info.type)
print()
运行脚本,您将获得以下输出:
student@ubuntu:~/work$ python3 read_metadata.py
Output:
work/bye.py
Size : 30 bytes
Type : b'0'
work/shutil_make_archive.py
Size : 243 bytes
Type : b'0'
work/check_archive_file.py
Size : 233 bytes
Type : b'0'
work/welcome.py
Size : 48 bytes
Type : b'0'
work/add_to_archive.py
Size : 491 bytes
Type : b'0'
work/shutil_unpack_archive.py
Size : 279 bytes
Type : b'0'
现在,我们将使用extractall()
函数从存档中提取内容。为此,创建一个名为extract_contents.py
的脚本,并在其中编写以下代码:
import tarfile
import os
os.mkdir('work')
with tarfile.open('work.tar', 'r') as t:
t.extractall('work')
print(os.listdir('work'))
运行脚本,您将获得以下输出:
student@ubuntu:~/work$ python3 extract_contents.py
检查您当前的工作目录,您将找到work/
目录。导航到该目录,您可以找到解压缩的文件。
在本节中,我们将使用 ZIP 文件。我们将学习python
的zipfile
模块,如何创建 ZIP 文件,如何测试输入的文件名是否为有效的zip
文件名,读取元数据等。
首先,我们将学习如何使用shutil
模块的make_archive()
功能创建zip
文件。创建一个名为make_zip_file.py
的脚本,并在其中编写以下代码:
import shutil
shutil.make_archive('work', 'zip', 'work')
按如下方式运行脚本:
student@ubuntu:~$ python3 make_zip_file.py
现在检查您当前的工作目录,您将看到work.zip
。
现在,我们将测试输入的文件名是否为zip
文件。为此,zipfile
模块具有is_zipfile()
功能。
创建一个名为check_zip_file.py
的脚本,并在其中写入以下内容:
import zipfile
for f_name in ['hello.py', 'work.zip', 'welcome.py', 'sample.txt', 'test.zip']:
try:
print('{:} {}'.format(f_name, zipfile.is_zipfile(f_name)))
except IOError as err:
print('{:} {}'.format(f_name, err))
按如下方式运行脚本:
student@ubuntu:~$ python3 check_zip_file.py
Output :
hello.py False
work.zip True
welcome.py False
sample.txt False
test.zip True
在本例中,我们使用了一个for
循环,其中我们检查列表中的文件名。is_zipfile()
函数将逐个检查文件名,并给出布尔值。
现在,我们将看到如何使用 Python 的zipfile
模块从存档的 ZIP 文件中读取元数据。创建一个名为read_metadata.py
的脚本,并在其中写入以下内容:
import zipfile
def meta_info(names):
with zipfile.ZipFile(names) as zf:
for info in zf.infolist():
print(info.filename)
if info.create_system == 0:
system = 'Windows'
elif info.create_system == 3:
system = 'Unix'
else:
system = 'UNKNOWN'
print("System :", system)
print("Zip Version :", info.create_version)
print("Compressed :", info.compress_size, 'bytes')
print("Uncompressed :", info.file_size, 'bytes')
print()
if __name__ == '__main__':
meta_info('work.zip')
按如下方式执行脚本:
student@ubuntu:~$ python3 read_metadata.py
Output:
sample.txt
System : Unix
Zip Version : 20
Compressed : 2 bytes
Uncompressed : 0 bytes
bye.py
System : Unix
Zip Version : 20
Compressed : 32 bytes
Uncompressed : 30 bytes
extract_contents.py
System : Unix
Zip Version : 20
Compressed : 95 bytes
Uncompressed : 132 bytes
shutil_make_archive.py
System : Unix
Zip Version : 20
Compressed : 160 bytes
Uncompressed : 243 bytes
为了获取关于zip
文件的元数据信息,我们使用了ZipFile
类的infolist()
方法。
在本节中,我们将学习 Python 的pyAesCrypt
模块。pyAesCrypt
是一个文件加密模块,使用AES256-CBC
对文件和二进制流进行加密/解密。
安装pyAesCrypt
如下:
pip3 install pyAesCrypt
创建一个名为file_encrypt.py
的脚本,并在其中编写以下代码:
import pyAesCrypt
from os import stat, remove
# encryption/decryption buffer size - 64K
bufferSize = 64 * 1024
password = "#Training"
with open("sample.txt", "rb") as fIn:
with open("sample.txt.aes", "wb") as fOut:
pyAesCrypt.encryptStream(fIn, fOut, password, bufferSize)
# get encrypted file size
encFileSize = stat("sample.txt.aes").st_size
按如下方式运行脚本:
student@ubuntu:~/work$ python3 file_encrypt.py
Output :
请检查您当前的工作目录。您将在其中找到sample.txt.aes
加密文件。
在本例中,我们已经提到了缓冲区大小和密码。接下来,我们提到了将被加密的文件名。在encryptStream
中,我们提到了fIn
,这是我们要加密的文件,fOut
,这是我们加密后的文件名。我们已将加密文件存储为sample.txt.aes
。
现在,我们将对sample.txt.aes
文件进行解密,以获取该文件的内容。创建一个名为file_decrypt.py
的脚本,并在其中写入以下内容:
import pyAesCrypt
from os import stat, remove
bufferSize = 64 * 1024
password = "#Training"
encFileSize = stat("sample.txt.aes").st_size
with open("sample.txt.aes", "rb") as fIn:
with open("sampleout.txt", "wb") as fOut:
try:
pyAesCrypt.decryptStream(fIn, fOut, password, bufferSize, encFileSize)
except ValueError:
remove("sampleout.txt")
按如下方式运行脚本:
student@ubuntu:~/work$ python3 file_decrypt.py
现在,检查您当前的工作目录。将创建一个名为sampleout.txt
的文件。那是你解密的文件。
在本例中,我们提到了要解密的文件名,即sample.txt.aes
。接下来,我们解密的文件将是sampleout.txt
。在decryptStream()
中,我们提到了fIn
,这是我们要解密的文件,fOut
,这是decrypted
文件的名称。
在本章中,我们学习了如何创建和提取归档文件。归档在管理文件、目录和数据方面起着重要作用。它还将文件和目录存储到单个文件中
我们详细了解了tarfile
和zipfile
Python 模块,它们使您能够创建、提取和测试归档文件。您将能够向已存档的文件中添加新文件、读取元数据、从存档中提取文件。您还学习了使用pyAescrypt
模块进行文件加密和解密
在下一章中,您将学习 python 中的文本处理和正则表达式。Python 有一个非常强大的名为正则表达式的库,它执行搜索和提取数据等任务。
- 我们可以使用密码保护压缩数据吗?如果是,怎么做?
- python 中的上下文管理器是什么?
- 什么是酸洗和解酸洗?
- python 中有哪些不同类型的函数?