Skip to content

Latest commit

 

History

History
396 lines (303 loc) · 13.1 KB

File metadata and controls

396 lines (303 loc) · 13.1 KB

六、文件归档、加密和解密

在上一章中,我们学习了如何处理文件、目录和数据。我们还学习了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 的shutiltarfile模块。在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 文件,所以我们得到了一个布尔值,Falsework.tar.gzsample.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 创建

在本节中,我们将使用 ZIP 文件。我们将学习pythonzipfile模块,如何创建 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文件的名称。

总结

在本章中,我们学习了如何创建和提取归档文件。归档在管理文件、目录和数据方面起着重要作用。它还将文件和目录存储到单个文件中

我们详细了解了tarfilezipfilePython 模块,它们使您能够创建、提取和测试归档文件。您将能够向已存档的文件中添加新文件、读取元数据、从存档中提取文件。您还学习了使用pyAescrypt模块进行文件加密和解密

在下一章中,您将学习 python 中的文本处理和正则表达式。Python 有一个非常强大的名为正则表达式的库,它执行搜索和提取数据等任务。

问题

  1. 我们可以使用密码保护压缩数据吗?如果是,怎么做?
  2. python 中的上下文管理器是什么?
  3. 什么是酸洗和解酸洗?
  4. python 中有哪些不同类型的函数?

进一步阅读