个性化阅读
专注于IT技术分析

在Python中使用Zip文件

本文概述

目录

  • 使用Zip文件的先决条件
  • 什么是Zip文件?
  • 用于Zip文件?

zipfile模块

例外情况

  • zipfile.BadZipFile
  • zipfile.LargeZipFile

  • zipfile.ZipFile
  • zipfile.ZipInfo

方法

  • zipfile.is_zipfile()

处理Zip文件

  • 提取一个Zip文件
  • 使用密码提取一个邮编
  • 创建Zip文件
  • 写入Zip文件
  • 将文件附加到压缩文件

问题

  • 解决问题的步骤
  • 尾注

使用Zip文件的先决条件

  • 你必须了解Python的文件处理才能了解Zip文件处理。如果你不知道文件处理, 请转到W3Schools文件处理部分以学习。
  • Python中的OOPS概念
  • Python概念, 例如条件, 循环, 函数, 类等,
  • 如果你不了解Python, 请参加srcmini的免费的Python数据科学入门课程, 以学习Python语言或阅读Python的官方文档。

打开此链接以下载我在接下来的部分中使用的所有Zip文件夹。

什么是Zip文件?

Zip是一种存档文件格式, 支持无损数据压缩。 Zip文件是包含一个或多个压缩文件的单个文件。

用于Zip文件?

  • 压缩文件可帮助你将所有相关文件放在一个地方。
  • 压缩文件有助于减小数据大小。
  • 通过许多连接, Zip文件的传输速度比单个文件快。

使用dir()方法探索zipfile模块的所有方法和类。请参阅代码以获取zipfile模块的所有类和方法。

import zipfile # importing the 'zipfile' module

print(dir(zipfile))
['BZIP2_VERSION', 'BadZipFile', 'BadZipfile', 'DEFAULT_VERSION', 'LZMACompressor', 'LZMADecompressor', 'LZMA_VERSION', 'LargeZipFile', 'MAX_EXTRACT_VERSION', 'PyZipFile', 'ZIP64_LIMIT', 'ZIP64_VERSION', 'ZIP_BZIP2', 'ZIP_DEFLATED', 'ZIP_FILECOUNT_LIMIT', 'ZIP_LZMA', 'ZIP_MAX_COMMENT', 'ZIP_STORED', 'ZipExtFile', 'ZipFile', 'ZipInfo', '_CD64_CREATE_VERSION', '_CD64_DIRECTORY_RECSIZE', '_CD64_DIRECTORY_SIZE', '_CD64_DISK_NUMBER', '_CD64_DISK_NUMBER_START', '_CD64_EXTRACT_VERSION', '_CD64_NUMBER_ENTRIES_THIS_DISK', '_CD64_NUMBER_ENTRIES_TOTAL', '_CD64_OFFSET_START_CENTDIR', '_CD64_SIGNATURE', '_CD_COMMENT_LENGTH', '_CD_COMPRESSED_SIZE', '_CD_COMPRESS_TYPE', '_CD_CRC', '_CD_CREATE_SYSTEM', '_CD_CREATE_VERSION', '_CD_DATE', '_CD_DISK_NUMBER_START', '_CD_EXTERNAL_FILE_ATTRIBUTES', '_CD_EXTRACT_SYSTEM', '_CD_EXTRACT_VERSION', '_CD_EXTRA_FIELD_LENGTH', '_CD_FILENAME_LENGTH', '_CD_FLAG_BITS', '_CD_INTERNAL_FILE_ATTRIBUTES', '_CD_LOCAL_HEADER_OFFSET', '_CD_SIGNATURE', '_CD_TIME', '_CD_UNCOMPRESSED_SIZE', '_ECD_COMMENT', '_ECD_COMMENT_SIZE', '_ECD_DISK_NUMBER', '_ECD_DISK_START', '_ECD_ENTRIES_THIS_DISK', '_ECD_ENTRIES_TOTAL', '_ECD_LOCATION', '_ECD_OFFSET', '_ECD_SIGNATURE', '_ECD_SIZE', '_EndRecData', '_EndRecData64', '_FH_COMPRESSED_SIZE', '_FH_COMPRESSION_METHOD', '_FH_CRC', '_FH_EXTRACT_SYSTEM', '_FH_EXTRACT_VERSION', '_FH_EXTRA_FIELD_LENGTH', '_FH_FILENAME_LENGTH', '_FH_GENERAL_PURPOSE_FLAG_BITS', '_FH_LAST_MOD_DATE', '_FH_LAST_MOD_TIME', '_FH_SIGNATURE', '_FH_UNCOMPRESSED_SIZE', '_SharedFile', '_Tellable', '_ZipDecrypter', '_ZipWriteFile', '__all__', '__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', '_check_compression', '_check_zipfile', '_get_compressor', '_get_decompressor', 'binascii', 'bz2', 'compressor_names', 'crc32', 'error', 'importlib', 'io', 'is_zipfile', 'lzma', 'main', 'os', 're', 'shutil', 'sizeCentralDir', 'sizeEndCentDir', 'sizeEndCentDir64', 'sizeEndCentDir64Locator', 'sizeFileHeader', 'stat', 'stringCentralDir', 'stringEndArchive', 'stringEndArchive64', 'stringEndArchive64Locator', 'stringFileHeader', 'struct', 'structCentralDir', 'structEndArchive', 'structEndArchive64', 'structEndArchive64Locator', 'structFileHeader', 'sys', 'threading', 'time', 'zlib']

你已经看到了许多正确的类和方法。但是, 你不会学习所有这些。你将仅学习一些使用Zip文件的类和方法。

让我们看一下一些有用的异常, 类和方法, 并进行简要说明。

例外情况

异常是一条消息, 用于根据你的喜好显示确切的错误。在Python中, 你可以使用try, 但最后一个关键字来进行错误处理。

如果你不熟悉错误处理, 请转至Pythons错误处理文档以了解错误处理。

让我们看看zipfile模块中的所有异常。

zipfile.BadZipFile

zipfile.BadZipFile是zipfile模块中的异常。错误的Zip文件将引发此错误。请参见下面的示例。

## zipfile.BadZipFile
import zipfile

def main():
    try:
        with zipfile.ZipFile('sample_file.zip') as file: # opening the zip file using 'zipfile.ZipFile' class
            print("Ok")
    except zipfile.BadZipFile: # if the zip file has any errors then it prints the error message which you wrote under the 'except' block
        print('Error: Zip file is corrupted')

if __name__ == '__main__': main()

## I used a badfile for the test
Ok

zipfile.LargeZipFile

假设如果要使用大型Zip文件, 则需要在打开Zip时启用ZIP64功能。如果你不启用它, LargeZipFile将提高。参见示例。

## zipfile.LargeZipFile
## Without enabling 'Zip64'
import zipfile

def main():
    try:
        with zipfile.ZipFile('sample_file.zip') as file:
            print('File size is compatible')
    except zipfile.LargeZipFile: # it raises an 'LargeZipFile' error because you didn't enable the 'Zip64'
        print('Error: File size if too large')

if __name__ == '__main__': main()
File size is compatible
## zipfile.LargeZipFile
## With enabling 'ZIP64'
import zipfile

def main():
    try:
        with zipfile.ZipFile('sample_file.zip', mode = 'r', allowZip64 = True) as file: # here enabling the 'Zip64'
            print('File size is compatible')
    except zipfile.LargeZipFile:
        print('Error: File size if too large') # if the file size is too large to open it prints the error you have written

if __name__ == '__main__': main()
File size is compatible

选择最适合异常处理的Zip文件, 然后尝试运行该程序。你将获得一个清晰的想法。

简而言之, 类是一组方法和属性。通过创建类的实例, 可以在任何需要的地方使用类方法和属性。

让我们看一下zipfile模块的一些类。

zipfile.ZipFile

用于Zip文件的最常见的类是ZipFile类。

zipfile.ZipFile用于写入和读取Zip文件。它具有一些用于处理Zip文件的方法。

现在, 使用dir()对象探索ZipFile类的方法。参见代码。

import zipfile

print(dir(zipfile.ZipFile)) # accessing the 'ZipFile' class
['_RealGetContents', '__class__', '__del__', '__delattr__', '__dict__', '__dir__', '__doc__', '__enter__', '__eq__', '__exit__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', '_extract_member', '_fpclose', '_open_to_write', '_sanitize_windows_name', '_windows_illegal_name_trans_table', '_write_end_record', '_writecheck', 'close', 'comment', 'extract', 'extractall', 'fp', 'getinfo', 'infolist', 'namelist', 'open', 'printdir', 'read', 'setpassword', 'testzip', 'write', 'writestr']

在前面的示例中, 你已经使用zipfile.ZipFile类读取Zip文件。

zipfile.ZipFile包含许多方法(例如解压缩, 打开getinfo, setpassword等)来处理Zip文件。

让我们看一下ZipFile类的一些方法。

## zipfile.ZipFile
import zipfile

def main():
    with zipfile.ZipFile('sample_file.zip') as file:

        # ZipFile.infolist() returns a list containing all the members of an archive file
        print(file.infolist())

        # ZipFile.namelist() returns a list containing all the members with names of an archive file
        print(file.namelist())

        # ZipFile.getinfo(path = filepath) returns the information about a member of Zip file.
        # It raises a KeyError if it doesn't contain the mentioned file
        print(file.getinfo(file.namelist()[-1]))

        # ZipFile.open(path = filepath, mode = mode_type, pwd = password) opens the members of an archive file
        # 'pwd' is optional -> if it has password mention otherwise leave it
        text_file = file.open(name = file.namelist()[-1], mode = 'r')

        # 'read()' method of the file prints all the content of the file. You see this method in file handling.
        print(text_file.read())  

        # You must close the file if you don't open a file using 'with' keyword
        # 'close()' method is used to close the file
        text_file.close()

        # ZipFile.extractall(path = filepath, pwd = password) extracts all the files to current directory
        file.extractall()
        # after executing check the directory to see extracted files


if __name__ == '__main__': main()
[<ZipInfo filename='extra_file.txt' filemode='-rw-rw-rw-' file_size=59>, <ZipInfo filename='READ ME.txt' filemode='-rw-rw-rw-' file_size=59>, <ZipInfo filename='even_odd.py' filemode='-rw-rw-rw-' file_size=129>]
['extra_file.txt', 'READ ME.txt', 'even_odd.py']
<ZipInfo filename='even_odd.py' filemode='-rw-rw-rw-' file_size=129>
b"num = int(input('Enter a Number:- '))\r\nif num % 2 == 0:\r\n\tprint('{} is Even'.fromat(num))\r\nelse:\r\n\tprint('{} is Odd'.fromat(num))"

如果要学习ZipFile类的所有方法, 请对要学习的方法使用help()函数。

或者转到Python的官方文档进行学习。

zipfile.ZipInfo

zipfile.ZipInfo类, 用于表示Zip文件夹的成员。

首先, 使用dir()方法浏览zipfile.ZipInfo类的所有对象。请参见下面的代码。

## zipfile.ZipInfo
import zipfile

print(dir(zipfile.ZipInfo))
['CRC', 'FileHeader', '__class__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__slots__', '__str__', '__subclasshook__', '_decodeExtra', '_encodeFilenameFlags', '_raw_time', 'comment', 'compress_size', 'compress_type', 'create_system', 'create_version', 'date_time', 'external_attr', 'extra', 'extract_version', 'file_size', 'filename', 'flag_bits', 'from_file', 'header_offset', 'internal_attr', 'is_dir', 'orig_filename', 'reserved', 'volume']

现在, 你将看到zipfile.ZipInfo类的一些方法

## zipfile.ZipInfo
import zipfile

def main():
    with zipfile.ZipFile('sample_file.zip') as file:

        # 'infolist()' is the object of 'ZipFile' class
        # 'infolist()' returns a list containing all the folders and files of the zip -> 'ZipInfo' objects
        # assigning last element of the list to a variable to test all the methods of 'ZipInfo'
        archive = file.infolist()
        read_me_file = archive[-1]

        # 'ZipInfo' methods

        # ZipInfo_object.filename returns the name of the file
        print("Name of the file:- {}".format(read_me_file.filename))

        # ZipInfo_object.file_size returns the size of the file
        print("Size of the file:- {}".format(read_me_file.file_size))

        # ZipInfo_object.is_dir() returns True if it's directory otherwise False
        print("Is directory:- {}".format(read_me_file.is_dir()))

        # ZipInfo_object.date_time() returns the created date & time of file
        print("File created data & time:- {}".format(read_me_file.date_time))

if __name__ == '__main__': main()
Name of the file:- sample_file/READ ME.txt
Size of the file:- 59
Is directory:- False
File created data & time:- (2018, 10, 4, 11, 32, 22)

如果你想了解有关ZipInfo对象的更多信息, 请转到ZipInfo。

方法

方法是程序中特定功能的代码块。例如, 如果要查找数字的绝对值, 则可以使用称为abs的Pythons方法。

你可以在任何需要的地方使用它。让我们看看zipfile模块的一些方法。

zipfile.is_zipfile()

如果文件是有效的Zip, 则zipfile模块的is_zipfile(filename)方法返回True, 否则返回False。

让我们来看一个例子。

## zipfile.is_zip(filename)
import zipfile

def main():
    print(zipfile.is_zipfile('sample_file.zip')) # it returns True

if __name__ == '__main__': main()
True

处理Zip文件

在本节中, 你将学习如何处理Zip文件, 例如打开, 提取, 编写等。

提取一个Zip文件

使用extractall方法将Zip文件的文件提取到当前目录。

## extracting zip file
import zipfile

def main():

    # assigning filename to a variable
    file_name = 'sample_file.zip'

    # opening Zip using 'with' keyword in read mode
    with zipfile.ZipFile(file_name, 'r') as file:
        # printing all the information of archive file contents using 'printdir' method
        print(file.printdir())

        # extracting the files using 'extracall' method
        print('Extracting all files...')
        file.extractall()
        print('Done!') # check your directory of zip file to see the extracted files

if __name__ == '__main__': main()
File Name                                             Modified             Size
sample_file/                                   2018-10-04 11:33:22            0
sample_file/even_odd.py                        2018-06-29 23:35:54          129
sample_file/READ ME.txt                        2018-10-04 11:32:22           59
None
Extracting all files...
Done!

使用密码提取一个邮编

要使用密码提取邮政编码, 你需要将值传递给extract(pwd = password)或extractall(pwd = password)方法的pwd位置参数。

你必须传递以字节为单位的密码。要将str转换为字节, 请使用utf-8编码格式的Python内置方法byte。

让我们来看一个例子。

## extracting zip with password
import zipfile

def main():
    file_name = 'pswd_file.zip'
    pswd = 'srcmini'

    with zipfile.ZipFile(file_name) as file:
        # password you pass must be in the bytes you converted 'str' into 'bytes'
        file.extractall(pwd = bytes(pswd, 'utf-8'))

if __name__ == '__main__': main()

你还可以使用ZipFile类的setpassword(pwd = password)方法提取文件。请参见下面的示例。

## extracting zip with password
import zipfile

def main():
    file_name = 'pswd_file.zip'
    pswd = 'srcmini'

    with zipfile.ZipFile(file_name) as file:
        # 'setpassword' method is used to give a password to the 'Zip'
        file.setpassword(pwd = bytes(pswd, 'utf-8'))
        file.extractall()

if __name__ == '__main__': main()

创建Zip文件

要创建一个Zip文件, 你不需要任何其他方法。只需将名称传递给ZipFile类, 它将在当前目录中创建一个存档。

请参见以下示例。

## Creating Zip file
import zipfile

def main():

    archive_name = 'example_file.zip'
    # below one line of code will create a 'Zip' in the current working directory
    with zipfile.ZipFile(archive_name, 'w') as file:
        print("{} is created.".format(archive_name))

if __name__ == '__main__': main()
example_file.zip is created.

写入Zip文件

你必须以写入模式打开Zip文件, 才能将文件写入存档文件。它会覆盖Zip中的所有现有文件。

举个例子。

## Writing files to zip
import zipfile

def main():

    file_name = 'sample_file.zip'

    # Opening the 'Zip' in writing mode
    with zipfile.ZipFile(file_name, 'w') as file:
        # write mode overrides all the existing files in the 'Zip.'
        # you have to create the file which you have to write to the 'Zip.'
        file.write('extra_file.txt')
        print('File overrides the existing files')

    # opening the 'Zip' in reading mode to check
    with zipfile.ZipFile(file_name, 'r') as file:
        print(file.namelist())

if __name__ == '__main__': main()
File overrides the existing files
['extra_file.txt']

将文件追加到Zip

你必须以append(a)模式打开Zip才能将任何文件附加到Zip。它不会覆盖现有文件。

让我们来看一个例子。

## Appending files to zip
import zipfile

def main():

    file_name = 'sample_file.zip'

    # opening the 'Zip' in writing mode
    with zipfile.ZipFile(file_name, 'a') as file:
        # append mode adds files to the 'Zip'
        # you have to create the files which you have to add to the 'Zip'
        file.write('READ ME.txt')
        file.write('even_odd.py')
        print('Files added to the Zip')

    # opening the 'Zip' in reading mode to check
    with zipfile.ZipFile(file_name, 'r') as file:
        print(file.namelist())

if __name__ == '__main__': main()
Files added to the Zip
['extra_file.txt', 'READ ME.txt', 'even_odd.py']

到目前为止, 你已经了解了如何处理Zip文件。现在, 你将能够打开, 编写, 附加, 提取, 创建等Zip文件。现在, 你将要编写一个简单的程序。

让我们看看它是什么?

使用循环和zipfile使用密码提取多个子邮政编码

  • 你有一个Zip, 其中包含一些子Zip文件。每个Zip文件都有一个密码, 即它们的名称。我们的挑战是解压缩所有Zip, 直到到达终点为止。

解决问题的步骤

  • 使用其名称作为密码提取父文件文件。
  • 使用namelist()方法获取第一个子名称。将其存储在变量中。

运行循环无限次。

使用is_zipfile()方法检查文件是否为Zip。如果是, 请执行以下操作。

  • 用name变量打开zip。
  • 从名称变量获取邮政编码的密码。
  • 提取邮政编码。
  • 获取下一个邮政编码名称并将其存储在名称变量中。

其他

  • 使用break中断循环。

我创建了上面的过程。如果需要, 可以根据文件排列进行更改。

## Solution
import zipfile

def main():

    # storing the parent name
    parent_file_name = '000.zip'

    with zipfile.ZipFile(parent_file_name, 'r') as parent_file:

        # extracting the parent file
        pswd = bytes(parent_file_name.split('.')[0], 'utf-8')
        parent_file.extractall(pwd = pswd)

        # getting the first child
        next_zip_name = parent_file.namelist()[0]

        # looping through the sub zips infinite times until you don't encouter a 'Zip' file
        while True:

            if zipfile.is_zipfile(next_zip_name):
                # opening the zip
                with zipfile.ZipFile(next_zip_name, 'r') as child_file:

                    # getting password from the zip name
                    pswd = bytes(next_zip_name.split('.')[0], 'utf-8')

                    # extracting the zip
                    child_file.extractall(pwd = pswd)

                    # getting the child zip name
                    next_zip_name = child_file.namelist()[0]
            else:
                break

if __name__ == '__main__': main()

执行完上述程序后, 你将看到所有子zip均被解压缩到当前目录。

尾注

恭喜你完成了本教程!

希望你喜欢本教程。当你使用Zip文件时, 本文对你有很大帮助。现在, 你可以使用Zip文件了。

如果你对本文有任何疑问, 请在评论部分中问我。我会尽快回复。

同样, 如果你不熟悉Python, 请参加srcmini的免费数据科学入门Python课程, 以学习Python语言或阅读Python的官方文档。

编码愉快!

赞(0)
未经允许不得转载:srcmini » 在Python中使用Zip文件

评论 抢沙发

评论前必须登录!