13.4. lzma — Compression via l’algorithme LZMA

Nouveau dans la version 3.3.

Code source : Lib/lzma.py


Ce module fournit des classes et des fonctions utiles pour compresser et décompresser des données en utilisant l’algorithme de compression LZMA. Ce module inclut aussi aussi une interface prenant en charge les fichiers .xz et son format originel .lzma utilisés par l’utilitaire xz, ainsi que les flux bruts compressés.

L’interface disponible par ce module ressemble en de nombreux points à celle du module bz2. Cependant, notez que la LZMAFile n’est pas thread-safe, comme l’est la bz2.BZ2File. Donc, si vous souhaitez utiliser une seule instance de LZMAFile pour plusieurs fils, il sera alors nécessaire de la protéger avec un verrou (lock).

exception lzma.LZMAError

Cette exception est levée dès lors qu’une erreur survient pendant la compression ou la décompression, ou pendant l’initialisation de l’état de la compression/décompression.

13.4.1. Lire et écrire des fichiers compressés

lzma.open(filename, mode="rb", *, format=None, check=-1, preset=None, filters=None, encoding=None, errors=None, newline=None)

Ouvre un fichier compressé sous LZMA en mode binaire ou texte, retourne un file object.

L’argument nom de fichier peut être soit le nom d’un fichier à créer (donné pour str, bytes ou un objet path-like), dont le fichier nommé reste ouvert, ou soit un objet fichier existant à lire ou à écrire.

L’argument mode peut être n’importe quel argument suivant : "r", "rb", "w", "wb", "x", "xb", "a" ou "ab" pour le mode binaire, ou "rt", "wt", "xt", ou "at" pour le mode texte. La valeur par défaut est "rb".

Quand un fichier est ouvert pour le lire, les arguments format et filters ont les mêmes significations que pour la LZMADecompressor. Par conséquent, les arguments check et preset ne devront pas être sollicités.

Dès ouverture d’un fichier pour l’écriture, les arguments format, check, preset et filters ont le même sens que dans la LZMACompressor.

Pour le mode binaire, cette fonction équivaut à la LZMAFile constructor: LZMAFile(filename, mode, ...). Dans ce cas précis, les arguments encoding, errors et newline ne sont pas accessibles.

Pour le mode texte, un objet de LZMAFile est créé, et enveloppé dans une instance de io.TextIOWrapper avec son encodage spécifique, son gestionnaire d’erreur, et ses signes pour les renvois à la ligne.

Modifié dans la version 3.4: Support ajouté pour les modes "x", "xb" and "xt".

Modifié dans la version 3.6: Accepte un path-like object.

class lzma.LZMAFile(filename=None, mode="r", *, format=None, check=-1, preset=None, filters=None)

Ouvre un fichier LZMA compressé en mode binaire.

An LZMAFile can wrap an already-open file object, or operate directly on a named file. The filename argument specifies either the file object to wrap, or the name of the file to open (as a str, bytes or path-like object). When wrapping an existing file object, the wrapped file will not be closed when the LZMAFile is closed.

L’argument mode peut être soit "r" pour la lecture (défaut), "w" pour la ré-écriture, "x" pour la création exclusive, ou "a" pour l’insertion. Elles epuvent aussi être écrites de la façon suivante : "rb", "wb", "xb" et "ab" respectivement.

Si l’argument filename est un objet fichier (plutôt qu’un nom de fichier courant), un mode`` »w »`` ne tronquera aucunement le fichier, et sera équivalent à "a".

Dès l’ouverture d’un fichier pour être lu, le fichier d’entrée peut être le résultat d’une concaténation de plusieurs flux distincts et compressés. Ceux-ci sont décodés de manière transparente en un seul flux logique.

Quand un fichier est ouvert pour le lire, les arguments format et filters ont les mêmes significations que pour la LZMADecompressor. Par conséquent, les arguments check et preset ne devront pas être sollicités.

Dès ouverture d’un fichier pour l’écriture, les arguments format, check, preset et filters ont le même sens que dans la LZMACompressor.

La LZMAFile supporte tous les attributs précisés dans io.BufferedIOBase, sauf detach() et truncate(). Le with et son itération sont également supportés.

Les méthodes suivantes sont aussi disponibles :

peek(size=-1)

Renvoie la donnée en mémoire-tampon sans progression de la position du fichier. Au moins un octet de donnée sera renvoyé, jusqu’à ce que l’EOF soit atteinte. Le nombre exact d’octets renvoyés demeure indéterminé (l’argument taille est ignoré).

Note

Alors que l’exécution de peek() ne change pas la position du fichier de la classe LZMAFile, la position de l’objet sous-jacent peut être modifiée (ex. : si la classe LZMAFile est construite en lui transmettant un fichier-objet comme filename).

Modifié dans la version 3.4: Support ajouté pour les modes "x" and "xb".

Modifié dans la version 3.5: La méthode read() accepte maintenant un argument None.

Modifié dans la version 3.6: Accepte un path-like object.

13.4.2. Compresser et décompresser une donnée en mémoire

class lzma.LZMACompressor(format=FORMAT_XZ, check=-1, preset=None, filters=None)

Créé un objet compresseur, qui peut être utilisé pour compresser incrémentalement une donnée.

Pour une façon plus adaptée de compresser un seul extrait de donnée, voir compress().

L’argument format définit quel format de conteneur sera mis en œuvre. Les valeurs possibles sont :

  • FORMAT_XZ: Le format du conteneur .xz.

    C’est le format par défaut.

  • FORMAT_ALONE: L’ancien format du conteneur .lzma.

    Ce format est davantage limité que .xz –il ne supporte pas les vérifications d’intégrité ou les filtres multiples.

  • FORMAT_RAW: Un flux de données brut, n’utilisant aucun format de conteneur.

    Ce format spécifique ne prend pas en charge les vérifications d’intégrité et exige systématiquement la définition d’une chaîne de filtrage personnalisée (à la fois pour la compression et la décompression). Par ailleurs, les données compressées par ce biais ne peuvent pas être décompressées par l’usage de FORMAT_AUTO (voir : LZMADecompressor).

L’argument check détermine le type de vérification d’intégrité à exploiter avec la donnée compressée. Cette vérification est déclenchée lors de la décompression, pour garantir que la donnée n’a pas été corrompue. Les valeurs possibles sont :

  • CHECK_NONE: Pas de vérification d’intégrité. C’est la valeur par défaut (et la seule valeur acceptable) pour FORMAT_ALONE et FORMAT_RAW.

  • CHECK_CRC32: Vérification par Redondance Cyclique 32-bit (Cyclic Redundancy Check).

  • CHECK_CRC64: Vérification par Redondance Cyclique 64-bit (Cyclic Redundancy Check). Valeur par défaut pour FORMAT_XZ.

  • CHECK_SHA256: Algorithme de Hachage Sécurisé 256-bit (Secure Hash Algorithm).

Si le type de vérification n’est pas supporté par le système, une erreur de type LZMAError est levée.

Les réglages de compression peuvent être définis soit comme un pré-réglage de niveau de compression (avec l’argument preset) ; soit de façon détaillée comme une chaîne particulière de filtres (avec l’argument filters).

L’argument preset (s’il est fourni) doit être un entier compris entre 0` et 9 (inclus), éventuellement relié à OR avec la constante PRESET_EXTREME. Si aucun preset ni filters ne ont définis, le comportement par défaut consiste à utiliser la PRESET_DEFAULT (niveau par défaut : 6). Des pré-réglages plus élevés entraîne une sortie plus petite, mais rend le processus de compression plus lent.

Note

En plus d’être plus gourmande en CPU, la compression avec des préréglages plus élevés nécessite beaucoup plus de mémoire (et produit des résultats qui nécessitent plus de mémoire pour décompresser). Par exemple, avec le préréglage 9, l’objet d’une LZMACompressor peut dépasser largement les 800 Mo. Pour cette raison, il est généralement préférable de respecter le préréglage par défaut.

L’argument filters (s’il est défini) doit être un critère de la chaîne de filtrage. Voir Préciser des chaînes de filtre personnalisées pour plus de précisions.

compress(data)

Une data compressée (un objet bytes), renvoie un objet bytes contenant une donnée compressée pour au moins une partie de l’entrée. Certaine data peuvent être mise en tampon, pour être utiliser lors de prochains appels par compress() et flush(). La donnée renvoyée pourra être concaténée avec la sortie d’appels précédents vers la méthode compress().

flush()

Conclut l’opération de compression, en renvoyant l’objet bytes constitué de toutes les données stockées dans les tampons interne du compresseur.

Le compresseur ne pourra pas être sollicité après l’appel de cette méthode.

class lzma.LZMADecompressor(format=FORMAT_AUTO, memlimit=None, filters=None)

Créé un objet de décompression, pour décompresser de façon incrémentale une donnée.

Pour un moyen plus pratique de décompresser un flux compressé complet en une seule fois, voir decompress().

L’argument format spécifie le format du conteneur à utiliser. La valeur par défaut est FORMAT_AUTO pouvant à la fois décompresser les fichiers .xz and .lzma. D’autres valeurs sont possibles comme FORMAT_XZ, FORMAT_ALONE, et FORMAT_RAW.

L’argument memlimit spécifie une limite (en octets) sur la quantité de mémoire que le décompresseur peut utiliser. Lorsque cet argument est utilisé, la décompression échouera avec une LZMAError s’il n’est pas possible de décompresser l’entrée dans la limite mémoire disponible.

L’argument filters spécifie la chaîne de filtrage utilisée pour créer le flux décompressé. Cet argument est requis si format est FORMAT_RAW, mais ne doit pas être utilisé pour d’autres formats. Voir Préciser des chaînes de filtre personnalisées pour plus d’informations sur les chaînes de filtrage.

Note

Cette classe ne gère pas de manière transparente les entrées contenant plusieurs flux compressés, contrairement à decompress() et LZMAFile. Pour décompresser une entrée multi-flux avec LZMADecompressor, vous devez créer un nouveau décompresseur à chaque flux.

decompress(data, max_length=-1)

Décompresse data (un bytes-like object), renvoyant une donnée non compressée en tant que chaîne d’octets. Certaines de ces data peuvent être mises en interne en tampon, pour un usage lors d’appels ultérieurs par la méthode decompress(). La donnée renvoyée doit être concaténée avec la sortie des appels précédents à la méthode decompress().

Si max_length est positif, renvoie au plus max_length octets de données compressées. Si la limite est atteinte et que d’autres sorties peuvent être produites, l’attribut needs_input est positionné sur False. Dans ce cas, lors de l’appel suivant à la méthode decompress(), vous pouvez fournir b'' dans data afin d’obtenir la suite de la sortie.

Si toutes les données entrées ont été décompressées et renvoyées (soit parce qu’il y avait moins de max_length octets, ou parce que max_length était négatif), l’attribut needs_input sera configuré sur True.

Essayer de décompresser des données après que la fin du flux soit atteinte lève une erreur EOFError. Toute donnée trouvée après la fin du flux est ignorée et sauvegardée dans l’attribut unused_data.

Modifié dans la version 3.5: Ajout du paramètre max_length.

check

L’ID de la vérification d’intégrité exploité par le flux entrant. Il s’agit de CHECK_UNKNOWN tant que ce flux a été décodé pour déterminer quel type de vérification d’intégrité à été utilisé.

eof

True si le marqueur de fin de flux a été atteint.

unused_data

Donnée trouvée après la fin du flux compressé.

Avant d’atteindre la fin du flux, ce sera b"".

needs_input

False si la méthode decompress() peut fournir plus de données décompressées avant l’acquisition d’une nouvelle entrée non compressée.

Nouveau dans la version 3.5.

lzma.compress(data, format=FORMAT_XZ, check=-1, preset=None, filters=None)

data compressée (un objet bytes), renvoyant une donnée compressée comme un objet bytes.

Voir LZMACompressor ci-dessus pour une description des arguments format, check, preset and filters.

lzma.decompress(data, format=FORMAT_AUTO, memlimit=None, filters=None)

Décopresse data (un objet bytes ), et retourne la donnée décompressée sous la forme d’un objet bytes.

Si data est le résultat de la concaténation de plusieurs fluxcompressés et distincts , il les décompresse tous, et retourne les résultats concaténés.

Voir LZMADecompressor ci-dessus pour une description des arguments format, memlimit et filters.

13.4.3. Divers

lzma.is_check_supported(check)

Renvoie vrai si le contrôle d’intégrité donné est supporté par le système.

CHECK_NONE et CHECK_CRC32 sont toujours suppportés. CHECK_CRC64 et CHECK_SHA256 peuvent être indisponibles si vous utlisez une version de liblzma compilée avec des possibilités restreintes.

13.4.4. Préciser des chaînes de filtre personnalisées

Une chaîne de filtres est une séquence de dictionnaires, où chaque dictionnaire contient l’ID et les options pour chaque filtre. Le moindre dictionnaire contient la clé "id" et peut aussicontenir d’autres clés pour préciser chaque options relative au filtre déclaré. Les ID valides des filtres sont définies comme suit :

  • Filtres de compression:
    • FILTER_LZMA1 (à utiliser avec FORMAT_ALONE)

    • FILTER_LZMA2 (à utiliser avec FORMAT_XZ et FORMAT_RAW)

  • Filtre Delta:
    • FILTER_DELTA

  • Filtres Branch-Call-Jump (BCJ):
    • FILTER_X86

    • FILTER_IA64

    • FILTER_ARM

    • FILTER_ARMTHUMB

    • FILTER_POWERPC

    • FILTER_SPARC

Une chaîne de filtres peut contenir jusqu’à 4 filtres, et ne peut pas être vide. Le dernier filtre de cette chaîne devra être un filtre de compression, et tous les autres doivent être des filtres delta ou BCJ.

Les filtres de compression contiennent les options suivantes (définies comme entrées additionnelles dans le dictionnaire qui représente le filtre) :

  • preset: Un pré-réglage à exploiter comme une source de valeurs par défaut pour les options qui ne sont pas explicitement définies.

  • dict_size: La taille du dictionnaire en octets. Comprise entre 4 Ko et 1.5 Go (inclus).

  • lc: Nombre de bits dans le contexte litéral.

  • lp: Nombre de bits dans la position litérale. La somme lc + lp devra être au moins 4.

  • pb: Nombre de bits à cette position ; au moins 4.

  • mode: MODE_FAST ou MODE_NORMAL.

  • nice_len: Ce qui devra être pris en compte comme « longueur appréciable » pour une recherche. Il devra être 273 ou moins.

  • mf: Quel type d’index de recherche à utiliser – MF_HC3, MF_HC4, MF_BT2, MF_BT3, ou MF_BT4.

  • depth: Profondeur maximum de la recherche, utilisée par l’index de recherche. 0 (défaut) signifie une sélection automatique basée sur des options de filtres différents.

Le filtre delta stocke les différences entre octets, induisant davantage d’entrées répétitives pour le compresseur, selon les circonstances. Il support une option, dist. Ce paramètre définit la distance entre les octets à soustraire. Par défaut : 1, soit la différence entre des octets adjacents.

Les filtres BCJ sont conçus pour être appliqués sur du langage machine. Ils convertissent les branches relatives, les appels et les sauts dans le code à des fins d’adressage strict, dans le but d’augmenter la redondance mise en jeu par le compresseur. Ils ne supportent qu’une seule option : start_offset, pour définir l’adresse où sera déclenché le début de la donnée d’entrée. Par défaut : 0.

13.4.5. Exemples

Lire un fichier compressé:

import lzma
with lzma.open("file.xz") as f:
    file_content = f.read()

Créer un fichier compressé:

import lzma
data = b"Insert Data Here"
with lzma.open("file.xz", "w") as f:
    f.write(data)

Compresser des données en mémoire:

import lzma
data_in = b"Insert Data Here"
data_out = lzma.compress(data_in)

Compression incrémentale:

import lzma
lzc = lzma.LZMACompressor()
out1 = lzc.compress(b"Some data\n")
out2 = lzc.compress(b"Another piece of data\n")
out3 = lzc.compress(b"Even more data\n")
out4 = lzc.flush()
# Concatenate all the partial results:
result = b"".join([out1, out2, out3, out4])

Ecrire des données compressées dans un fichier préalablement ouvert:

import lzma
with open("file.xz", "wb") as f:
    f.write(b"This data will not be compressed\n")
    with lzma.open(f, "w") as lzf:
        lzf.write(b"This *will* be compressed\n")
    f.write(b"Not compressed\n")

Créer un fichier compressé en utilisant une chaîne de filtre personnalisée:

import lzma
my_filters = [
    {"id": lzma.FILTER_DELTA, "dist": 5},
    {"id": lzma.FILTER_LZMA2, "preset": 7 | lzma.PRESET_EXTREME},
]
with lzma.open("file.xz", "w", filters=my_filters) as f:
    f.write(b"blah blah blah")