13.5. "zipfile" --- Trabalha com arquivos ZIP
*********************************************

**Código Fonte:** Lib/zipfile.py

======================================================================

O formato de arquivo ZIP é um padrão de compactação e arquivamento.
Este módulo fornece ferramentas para criar, ler, escrever, adicionar,
e listar um arquivo ZIP. Qualquer uso avançado deste módulo vai exigir
um entendimento do formato, como definido em PKZIP Application Note.

Esse módulo atualmente não suporta arquivos ZIP multi-disco. Ele pode
lidar com arquivos ZIP que usam as extensões ZIP64 (ou seja arquivos
ZIP com tamanho maior do que 4 Gb). Ele suporta descriptografia de
arquivos criptografados dentro do ZIP, mas atualmente não pode criar
um arquivo criptografado. A descriptografia é extremamente lenta pois
é implementada em Python nativo ao invés de C.

Este módulo define os seguintes itens:

exception zipfile.BadZipFile

   Este erro ocorre para arquivos ZIP corrompidos.

   Novo na versão 3.2.

exception zipfile.BadZipfile

   Alias para "BadZipFile", para compatibilidade com versões mais
   antigas de Python.

   Obsoleto desde a versão 3.2.

exception zipfile.LargeZipFile

   Este erro ocorre quando um arquivo ZIP precisa da funcionalidade
   ZIP64 que não está habilitada.

class zipfile.ZipFile

   A classe para ler e escrever arquivos ZIP. Veja a seçã Objetos
   ZipFile para detalhes do construtor.

class zipfile.PyZipFile

   Classe para criar arquivos ZIP contendo bibliotecas Python.

class zipfile.ZipInfo(filename='NoName', date_time=(1980, 1, 1, 0, 0, 0))

   Classe usada para representar informação sobre um membro de um
   archive. Instâncias desta classe são retornadas pelos métodos
   "getinfo()" e "infolist()" de objetos da classe "ZipFile". A
   maioria dos usuários do módulo "zipfile" não vai precisar criar,
   mas apenas usar objetos criados pelo módulo. *filename* deveria ser
   o caminho completo do membro do arquivo, e *date_time* deveria ser
   uma tupla contendo seis campos que descrevem o momento da última
   modificação no arquivo; os campos são descritos na seção Objetos
   ZipInfo.

zipfile.is_zipfile(filename)

   Retorna "True" se *filename* é um arquivo ZIP válido baseado no seu
   magic number, caso contrário retorna "False". *filename* pode ser
   um arquivo ou um file-like também.

   Alterado na versão 3.1: Suporte para arquivo e objetos file-like.

zipfile.ZIP_STORED

   Constante numérica para um membro de um arquivo descompactado

zipfile.ZIP_DEFLATED

   Constante numérica para o método de compactação usual. Requer o
   módulo "zlib" .

zipfile.ZIP_BZIP2

   Código numérico para o método de compactação BZIP2. Requer o módulo
   "bz2".

   Novo na versão 3.3.

zipfile.ZIP_LZMA

   Código numérico para o método de compactação LZMA. Requer o módulo
   "lzma".

   Novo na versão 3.3.

   Nota:

     A especificação do formato ZIP incluiu suporte para compactação
     bzip2 desde 2001, e para compactação LZMA desde 2006. Porém,
     algumas ferramentas (incluindo versões mais antigas de Python)
     não suportam esses métodos de compactação, e podem recusar
     processar o arquivo ZIP como um todo, ou falhar em extrair
     arquivos individuais.

Ver também:

  PKZIP Application Note
     Documentação do formato de arquivo ZIP feita por Phil Katz,
     criador do formato e dos algoritmos usados.

  Info-ZIP Home Page
     Informações sobre o programas de arquivamento e desenvolvimento
     de bibliotecas do projeto Info-ZIP


13.5.1. Objetos ZipFile
=======================

class zipfile.ZipFile(file, mode='r', compression=ZIP_STORED, allowZip64=True)

   Open a ZIP file, where *file* can be a path to a file (a string), a
   file-like object or a *path-like object*. The *mode* parameter
   should be "'r'" to read an existing file, "'w'" to truncate and
   write a new file, "'a'" to append to an existing file, or "'x'" to
   exclusively create and write a new file. If *mode* is "'x'" and
   *file* refers to an existing file, a "FileExistsError" will be
   raised. If *mode* is "'a'" and *file* refers to an existing ZIP
   file, then additional files are added to it.  If *file* does not
   refer to a ZIP file, then a new ZIP archive is appended to the
   file.  This is meant for adding a ZIP archive to another file (such
   as "python.exe").  If *mode* is "'a'" and the file does not exist
   at all, it is created. If *mode* is "'r'" or "'a'", the file should
   be seekable. *compression* is the ZIP compression method to use
   when writing the archive, and should be "ZIP_STORED",
   "ZIP_DEFLATED", "ZIP_BZIP2" or "ZIP_LZMA"; unrecognized values will
   cause "NotImplementedError" to be raised.  If "ZIP_DEFLATED",
   "ZIP_BZIP2" or "ZIP_LZMA" is specified but the corresponding module
   ("zlib", "bz2" or "lzma") is not available, "RuntimeError" is
   raised. The default is "ZIP_STORED".  If *allowZip64* is "True"
   (the default) zipfile will create ZIP files that use the ZIP64
   extensions when the zipfile is larger than 4 GiB. If it is  false
   "zipfile" will raise an exception when the ZIP file would require
   ZIP64 extensions.

   Se o arquivo é criado com modo "'w'", "'x'" ou "'a'" e então
   "closed()" sem adicionar nada ao arquivo, a estrutura própria para
   um arquivo vazio será escrita no arquivo.

   ZipFile is also a context manager and therefore supports the "with"
   statement.  In the example, *myzip* is closed after the "with"
   statement's suite is finished---even if an exception occurs:

      with ZipFile('spam.zip', 'w') as myzip:
          myzip.write('eggs.txt')

   Novo na versão 3.2: Adicionado o uso de "ZipFile" como um
   gerenciador de contexto.

   Alterado na versão 3.3: Adicionado suporte para compactação "bzip2
   ` e :mod:`lzma".

   Alterado na versão 3.4: Extensões ZIP64 são habilitadas por padrão.

   Alterado na versão 3.5: Adicionado suporte para escrever em streams
   não percorríveis. Adicionado suporte ao modo "'x'".

   Alterado na versão 3.6: Anteriormente, um simples "RuntimeError"
   era lançado para valores de compactação desconhecidos.

   Alterado na versão 3.6.2: O parâmetro *file* aceita um *objeto
   path-like*.

ZipFile.close()

   Fecha o arquivo. Você deve chamar "close()" antes de sair do seu
   programa ou registros essenciais não serão gravados.

ZipFile.getinfo(name)

   Retorna um objeto "ZipInfo" com informações sobre o *name* do
   membro do arquivo. Chamar "getinfo()" para um nome não encontrado
   no arquivo lança um "KeyError".

ZipFile.infolist()

   Retorna uma lista contendo um objeto "ZipInfo" para cada membro do
   arquivo. Os objetos estão na mesma ordem das entradas no arquivo
   ZIP em disco se um arquivo existente foi aberto.

ZipFile.namelist()

   Retorna uma lista de membros do arquivo por nome.

ZipFile.open(name, mode='r', pwd=None, *, force_zip64=False)

   Acessa um membro do arquivo como um objeto binário file-like.
   *name* pode ser o nome de um arquivo membro ou um objeto "ZipInfo".
   O parâmetro *mode*, se informado, deve ser "'r'" (valor padrão) or
   "'w'". *pwd* é a senha usada para descriptografar arquivos ZIP
   criptografados.

   "open()" também é um gerenciador de contexto e portanto suporta
   declarações com "with"

      with ZipFile('spam.zip') as myzip:
          with myzip.open('eggs.txt') as myfile:
              print(myfile.read())

   With *mode* "'r'" the file-like object ("ZipExtFile") is read-only
   and provides the following methods: "read()", "readline()",
   "readlines()", "__iter__()", "__next__()".  These objects can
   operate independently of the ZipFile.

   Com "mode='w'", é retornado um handle de arquivo, que suporta o
   método "write()". Quando um handle de arquivo modificável é aberto,
   tentativas de ler ou gravar outros arquivos no arquivo ZIP lança um
   "ValueError".

   Ao gravar um arquivo, se o tamanho do arquivo não é conhecido mas
   pode exceder 2 Gb, passe "force_zip64=True" para assegurar que o
   formato do header é capaz de suportar arquivos grandes. Se o
   tamanho do arquivo é conhecido, construa um objeto "ZipInfo" com
   "file_size" informado, então use-o como parâmetro *name*.

   Nota:

     Os métodos "open()", "read()" e "extract()" podem receber um nome
     de arquivo ou um objeto "ZipInfo". Voce vai gostar disso quando
     tentar ler um arquivo ZIP que contém membros com nomes
     duplicados.

   Alterado na versão 3.6: Removido suporte ao "mode='U'". Uso de
   "io.TextIOWrapper" para leitura de arquivos texto compactados em
   modo *universal newlines*.

   Alterado na versão 3.6: "open()" agora pode ser usado para gravar
   arquivos com a opção "mode='w'".

   Alterado na versão 3.6: Chamar "open()" em um ZipFile fechado lança
   um "ValueError". Anteriormente, um "RuntimeError" era lançado.

ZipFile.extract(member, path=None, pwd=None)

   Extrai um membro do arquivo para o diretório atual; *member* deve
   ser o nome complelto ou um objeto "ZipInfo". A informação  do
   arquivo é extraída com maior precisão possível. *path* especifica
   um outro diretório em que deve ser gravado. *member* pode ser um
   nome de arquivo ou um objeto "ZipInfo". *pwd* é a senha usada para
   criptografar arquivos.

   Retorna o caminho normalizado criado (um diretório ou novo
   arquivo).

   Nota:

     Se um nome de arquivo membro é um caminho absoluto, o drive/UNC e
     barras no início serão removidos, por exemplo: "///foo/bar" se
     torna "foo/bar" no Unix, e "C:\foo\bar" vira "foo\bar" no
     Windows. E todos os componentes "".."" no nome de um arquivo
     membro serão removidos, por exemplo: "../../foo../../ba..r" vira
     "foo../ba..r". No Windows caracteres ilegais (":", "<", ">", "|",
     """, "?", and "*") são substituídos por underscore ("_").

   Alterado na versão 3.6: Chamar "extract()" em um ZipFile fechado
   lança um "ValueError". Anteriormente, um "RuntimeError" era
   lançado.

   Alterado na versão 3.6.2: O parâmetro *path* aceita um objeto :term
   :>>`<<path-like.

ZipFile.extractall(path=None, members=None, pwd=None)

   Extrai todos os membros de um arquivo para o diretório atual.
   *path* especifica um diretório diferente para gravar os arquivos
   extraídos. *members* é opcional e deve ser um sub-conjunto da lista
   retornada por "namelist()". *pwd* é uma senha usada para
   criptografar arquivos.

   Aviso:

     Nunca extraia arquivos de fontes não confiáveis sem inspeção
     prévia. É possível que os arquivos sejam criados fora do *path*,
     por exemplo membros que tem nomes absolutos de arquivos começando
     com ""/"" ou nomes com dois pontos "".."". Este módulo tenta
     prevenir isto. Veja nota em "extract()".

   Alterado na versão 3.6: Chamar "extractall()" em um ZipFile fechado
   lança um "ValueError". Anteriormente, um "RuntimeError" era
   lançado.

   Alterado na versão 3.6.2: O parâmetro *path* aceita um objeto :term
   :>>`<<path-like.

ZipFile.printdir()

   Imprime a tabela de conteúdos de um arquivo para "sys.stdout".

ZipFile.setpassword(pwd)

   Seta *pwd* como senha padrão para extrair arquivos criptografados.

ZipFile.read(name, pwd=None)

   Retorna os bytes do arquivo *name* no arquivo compactado. *name* é
   o nome do arquivo no arquivo compactado, ou um objeto "ZipInfo". O
   arquivo compactado deve estar aberto para leitura ou append. *pwd*
   é a senha usada para criptografar arquivos e, se especificada, vai
   sobrepor a senha padrão configurada com "setpassword()". Chamar
   "read()" em um ZipFile que use um método de compactação diferente
   de "ZIP_STORED", "ZIP_DEFLATED", "ZIP_BZIP2" ou "ZIP_LZMA" lança um
   "NotImplementedError". Um erro também é lançado se o módulo de
   compactação correspondente não está disponível.

   Alterado na versão 3.6: Chamar "read()" em um ZipFile fechado lança
   um "ValueError". Anteriormente, um "RuntimeError" era lançado.

ZipFile.testzip()

   Lê todos os arquivos no arquivo compactado e verifica seus CRC's e
   cabeçalhos de arquivo. Retorna o nome do primeiro arquivo
   corrompido, or então retorna "None".

   Alterado na versão 3.6: Chamar "testzip()" em um ZipFile fechado
   lança um "ValueError". Anteriormente, um "RuntimeError" era
   lançado.

ZipFile.write(filename, arcname=None, compress_type=None)

   Write the file named *filename* to the archive, giving it the
   archive name *arcname* (by default, this will be the same as
   *filename*, but without a drive letter and with leading path
   separators removed).  If given, *compress_type* overrides the value
   given for the *compression* parameter to the constructor for the
   new entry. The archive must be open with mode "'w'", "'x'" or
   "'a'".

   Nota:

     Nomes de arquivo compactado devem ser relativos a raiz do mesmo,
     isto é, não devem começar com um separador de caminho.

   Nota:

     Se "arcname" (ou "filename", se "arcname" não for informado)
     contém um byte nulo, o nome do arquivo no arquivo compactado será
     truncado no byte nulo.

   Alterado na versão 3.6: Chamar "write()" em um ZipFile criado com
   modo "'r'" ou em um ZipFile fechado lança um "ValueError".
   Anteriormente, um "RuntimeError" era lançado.

ZipFile.writestr(zinfo_or_arcname, data[, compress_type])

   Grava um arquivo no arquivo compactado. O conteúdo é *data*, que
   pode ser uma instância de "str" ou de "bytes";  Se é uma "str", ela
   é encodada como UTF-8 primeiro. *zinfo_or_arcname* é o nome que
   será dado ao arquivo no arquivo compactado, ou uma instância de
   "ZipInfo". Se é uma instância, pelo menos o nome do arquivo, a
   data, e a hora devem ser informados. Se é um nome, a data e hora
   recebem a data e hora atual. O arquivo compactado deve ser aberto
   em modo "'w'", "'x'" ou "'a'".

   If given, *compress_type* overrides the value given for the
   *compression* parameter to the constructor for the new entry, or in
   the *zinfo_or_arcname* (if that is a "ZipInfo" instance).

   Nota:

     Quando é passada uma instância de "ZipInfo" ou o parâmetro
     *zinfo_or_arcname*, o método de compactação usado será aquele
     especificado no *compress_type* do objeto "ZipInfo". Por padrão,
     o construtor da classe "ZipInfo" seta este membro para
     "ZIP_STORED".

   Alterado na versão 3.2: O argumento *compress_type*.

   Alterado na versão 3.6: Chamar "writestr()" em um ZipFile criado
   com modo "'r'" ou em um ZipFile fechado lança um "ValueError".
   Anteriormente, um "RuntimeError" era lançado.

Os seguintes atributos de dados também estão disponíveis:

ZipFile.filename

   Nome do arquivo ZIP.

ZipFile.debug

   O nível de saída de debug para usar. Pode ser setado de *0`* (valor
   padrão, sem nenhuma saída) a "3" (com mais saída). A informação de
   debug é escrita em "sys.stdout".

ZipFile.comment

   The comment associated with the ZIP file as a "bytes" object. If
   assigning a comment to a "ZipFile" instance created with mode
   "'w'", "'x'" or "'a'", it should be no longer than 65535 bytes.
   Comments longer than this will be truncated.


13.5.2. Objetos PyZipFile
=========================

The "PyZipFile" constructor takes the same parameters as the "ZipFile"
constructor, and one additional parameter, *optimize*.

class zipfile.PyZipFile(file, mode='r', compression=ZIP_STORED, allowZip64=True, optimize=-1)

   Novo na versão 3.2: The *optimize* parameter.

   Alterado na versão 3.4: Extensões ZIP64 são habilitadas por padrão.

   Instances have one method in addition to those of "ZipFile"
   objects:

   writepy(pathname, basename='', filterfunc=None)

      Search for files "*.py" and add the corresponding file to the
      archive.

      If the *optimize* parameter to "PyZipFile" was not given or
      "-1", the corresponding file is a "*.pyc" file, compiling if
      necessary.

      If the *optimize* parameter to "PyZipFile" was "0", "1" or "2",
      only files with that optimization level (see "compile()") are
      added to the archive, compiling if necessary.

      If *pathname* is a file, the filename must end with ".py", and
      just the (corresponding "*.pyc") file is added at the top level
      (no path information).  If *pathname* is a file that does not
      end with ".py", a "RuntimeError" will be raised.  If it is a
      directory, and the directory is not a package directory, then
      all the files "*.pyc" are added at the top level.  If the
      directory is a package directory, then all "*.pyc" are added
      under the package name as a file path, and if any subdirectories
      are package directories, all of these are added recursively.

      *basename* is intended for internal use only.

      *filterfunc*, if given, must be a function taking a single
      string argument.  It will be passed each path (including each
      individual full file path) before it is added to the archive.
      If *filterfunc* returns a false value, the path will not be
      added, and if it is a directory its contents will be ignored.
      For example, if our test files are all either in "test"
      directories or start with the string "test_", we can use a
      *filterfunc* to exclude them:

         >>> zf = PyZipFile('myprog.zip')
         >>> def notests(s):
         ...     fn = os.path.basename(s)
         ...     return (not (fn == 'test' or fn.startswith('test_')))
         >>> zf.writepy('myprog', filterfunc=notests)

      The "writepy()" method makes archives with file names like this:

         string.pyc                   # Top level name
         test/__init__.pyc            # Package directory
         test/testall.pyc             # Module test.testall
         test/bogus/__init__.pyc      # Subpackage directory
         test/bogus/myfile.pyc        # Submodule test.bogus.myfile

      Novo na versão 3.4: The *filterfunc* parameter.

      Alterado na versão 3.6.2: The *pathname* parameter accepts a
      *path-like object*.


13.5.3. Objetos ZipInfo
=======================

Instances of the "ZipInfo" class are returned by the "getinfo()" and
"infolist()" methods of "ZipFile" objects.  Each object stores
information about a single member of the ZIP archive.

There is one classmethod to make a "ZipInfo" instance for a filesystem
file:

classmethod ZipInfo.from_file(filename, arcname=None)

   Construct a "ZipInfo" instance for a file on the filesystem, in
   preparation for adding it to a zip file.

   *filename* should be the path to a file or directory on the
   filesystem.

   If *arcname* is specified, it is used as the name within the
   archive. If *arcname* is not specified, the name will be the same
   as *filename*, but with any drive letter and leading path
   separators removed.

   Novo na versão 3.6.

   Alterado na versão 3.6.2: The *filename* parameter accepts a *path-
   like object*.

Instances have the following methods and attributes:

ZipInfo.is_dir()

   Return "True" if this archive member is a directory.

   This uses the entry's name: directories should always end with "/".

   Novo na versão 3.6.

ZipInfo.filename

   Name of the file in the archive.

ZipInfo.date_time

   The time and date of the last modification to the archive member.
   This is a tuple of six values:

   +---------+----------------------------+
   | Index   | Valor                      |
   |=========|============================|
   | "0"     | Year (>= 1980)             |
   +---------+----------------------------+
   | "1"     | Month (one-based)          |
   +---------+----------------------------+
   | "2"     | Day of month (one-based)   |
   +---------+----------------------------+
   | "3"     | Hours (zero-based)         |
   +---------+----------------------------+
   | "4"     | Minutos (base zero)        |
   +---------+----------------------------+
   | "5"     | Seconds (zero-based)       |
   +---------+----------------------------+

   Nota:

     The ZIP file format does not support timestamps before 1980.

ZipInfo.compress_type

   Type of compression for the archive member.

ZipInfo.comment

   Comment for the individual archive member as a "bytes" object.

ZipInfo.extra

   Expansion field data.  The PKZIP Application Note contains some
   comments on the internal structure of the data contained in this
   "bytes" object.

ZipInfo.create_system

   System which created ZIP archive.

ZipInfo.create_version

   PKZIP version which created ZIP archive.

ZipInfo.extract_version

   PKZIP version needed to extract archive.

ZipInfo.reserved

   Must be zero.

ZipInfo.flag_bits

   ZIP flag bits.

ZipInfo.volume

   Volume number of file header.

ZipInfo.internal_attr

   Internal attributes.

ZipInfo.external_attr

   External file attributes.

ZipInfo.header_offset

   Byte offset to the file header.

ZipInfo.CRC

   CRC-32 do arquivo não comprimido.

ZipInfo.compress_size

   Size of the compressed data.

ZipInfo.file_size

   Size of the uncompressed file.


13.5.4. Interface de Linha de Comando
=====================================

The "zipfile" module provides a simple command-line interface to
interact with ZIP archives.

If you want to create a new ZIP archive, specify its name after the
"-c" option and then list the filename(s) that should be included:

   $ python -m zipfile -c monty.zip spam.txt eggs.txt

Passing a directory is also acceptable:

   $ python -m zipfile -c monty.zip life-of-brian_1979/

If you want to extract a ZIP archive into the specified directory, use
the "-e" option:

   $ python -m zipfile -e monty.zip target-dir/

For a list of the files in a ZIP archive, use the "-l" option:

   $ python -m zipfile -l monty.zip


13.5.4.1. Opções de linha de comando
------------------------------------

-l <zipfile>

   List files in a zipfile.

-c <zipfile> <source1> ... <sourceN>

   Create zipfile from source files.

-e <zipfile> <output_dir>

   Extract zipfile into target directory.

-t <zipfile>

   Test whether the zipfile is valid or not.
