821 votes

Comment créer une archive zip d'un répertoire ?

Comment puis-je créer une archive zip d'une structure de répertoire en Python ?

74 votes

N'utilisez pas la solution proposée dans la réponse acceptée mais celle qui se trouve plus bas en utilisant make_archive de shutil (si vous voulez zipper un seul répertoire de manière récursive).

2042voto

crdavis Points 18

Le moyen le plus simple est d'utiliser shutil.make_archive . Il prend en charge les formats zip et tar.

import shutil
shutil.make_archive(output_filename, 'zip', dir_name)

Si vous avez besoin de faire quelque chose de plus compliqué que de compresser l'ensemble du répertoire (par exemple, sauter certains fichiers), vous devrez vous plonger dans l'application zipfile comme d'autres l'ont suggéré.

271 votes

shutil fait partie de la bibliothèque standard de Python. Ceci devrait être la première réponse

12 votes

Il s'agit de la réponse la plus concise et elle présente également l'avantage d'ajouter directement tous les sous-répertoires et fichiers à l'archive, plutôt que de tout inclure dans un dossier de niveau supérieur (ce qui entraîne un niveau redondant dans la structure du dossier lors de la décompression).

3 votes

@cmcginty pourriez-vous être un peu plus précis quant à l'aspect qui n'est pas thread-safe ? Est-ce que l'exécution de plusieurs threads pendant que l'un d'entre eux appelle cette fonction fera planter l'interpréteur ?

700voto

Mark Byers Points 318575

Comme d'autres l'ont souligné, vous devriez utiliser fichier zip . La documentation vous indique les fonctions disponibles, mais n'explique pas vraiment comment vous pouvez les utiliser pour zipper un répertoire entier. Je pense que le plus simple est de l'expliquer avec un exemple de code :

import os
import zipfile

def zipdir(path, ziph):
    # ziph is zipfile handle
    for root, dirs, files in os.walk(path):
        for file in files:
            ziph.write(os.path.join(root, file), 
                       os.path.relpath(os.path.join(root, file), 
                                       os.path.join(path, '..')))

with zipfile.ZipFile('Python.zip', 'w', zipfile.ZIP_DEFLATED) as zipf:
    zipdir('tmp/', zipf)

150 votes

J'ajouterais un deuxième argument à l'appel de l'écriture, en passant os.path.relpath(os.path.join(root, file), os.path.join(path, '..')) . Cela vous permettrait de compresser un répertoire à partir de n'importe quel répertoire de travail, sans obtenir les chemins absolus complets dans l'archive.

13 votes

Il y a une drôle de récursion lorsque j'essaie de compresser un dossier et d'envoyer le résultat de la compression dans le même dossier :-)

38 votes

shutil le rend très facile en une seule ligne. Veuillez vérifier la réponse ci-dessous

87voto

Ben James Points 41165

Pour ajouter le contenu de mydirectory dans un nouveau fichier zip, incluant tous les fichiers et sous-répertoires :

import os
import zipfile

zf = zipfile.ZipFile("myzipfile.zip", "w")
for dirname, subdirs, files in os.walk("mydirectory"):
    zf.write(dirname)
    for filename in files:
        zf.write(os.path.join(dirname, filename))
zf.close()

0 votes

Pour moi, ce code jette l'erreur suivante TypeError : invalid file : <zipfile.ZipFile [closed]>.

22 votes

Ne pouvez-vous pas utiliser un with au lieu de devoir appeler close() vous-même à la fin ?

0 votes

Exemple : ` avec zipfile.ZipFile("myzipfile.zip", "w") as zf : pass `

44voto

George V. Reilly Points 5471

Cette fonction va zipper récursivement une arborescence de répertoires, en comprimant les fichiers, et en enregistrant les noms de fichiers relatifs corrects dans l'archive. Les entrées de l'archive sont les mêmes que celles générées par zip -r output.zip source_dir .

import os
import zipfile
def make_zipfile(output_filename, source_dir):
    relroot = os.path.abspath(os.path.join(source_dir, os.pardir))
    with zipfile.ZipFile(output_filename, "w", zipfile.ZIP_DEFLATED) as zip:
        for root, dirs, files in os.walk(source_dir):
            # add directory (needed for empty dirs)
            zip.write(root, os.path.relpath(root, relroot))
            for file in files:
                filename = os.path.join(root, file)
                if os.path.isfile(filename): # regular files only
                    arcname = os.path.join(os.path.relpath(root, relroot), file)
                    zip.write(filename, arcname)

0 votes

Cela devrait être la réponse acceptée.

14voto

user1603862 Points 49

Pour ajouter la compression au fichier zip résultant, consultez le site ce lien .

Tu dois changer :

zip = zipfile.ZipFile('Python.zip', 'w')

à

zip = zipfile.ZipFile('Python.zip', 'w', zipfile.ZIP_DEFLATED)

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X