IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Python Discussion :

"IOError: [Errno 2] No such file or directory" a l'extraction d'une archive zip


Sujet :

Python

  1. #1
    Membre régulier
    Homme Profil pro
    Ingénieur validation
    Inscrit en
    Juin 2012
    Messages
    89
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingénieur validation
    Secteur : High Tech - Matériel informatique

    Informations forums :
    Inscription : Juin 2012
    Messages : 89
    Points : 70
    Points
    70
    Par défaut "IOError: [Errno 2] No such file or directory" a l'extraction d'une archive zip
    Bonjour,

    Avec le code suivant, j'arrive à extraire certaines archives zip, mais d'autres ne fonctionnent pas.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    import os
    import zipfile
     
    os.chdir(C:/Users/Admin/Downloads)
     
    mon_zip=zipfile.ZipFile('C:/Users/Admin/Downloads/NG659C1_treatment_resource.zip')
    mon_zip.extractall()
    Voici l'erreur que j'obtiens avec certaines archives
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    Traceback (most recent call last):
      File "<input>", line 1, in <module>
      File "C:\Python27\lib\zipfile.py", line 1040, in extractall
        self.extract(zipinfo, path, pwd)
      File "C:\Python27\lib\zipfile.py", line 1028, in extract
        return self._extract_member(member, path, pwd)
      File "C:\Python27\lib\zipfile.py", line 1083, in _extract_member
        file(targetpath, "wb") as target:
    IOError: [Errno 2] No such file or directory: 'C:\\Users\\Admin\\Downloads\\NG659C1_11_09_2018_09_16_47_treatment_resource\\A350_TRT_047\\CRDC_A01'
    En fait dans le dossier Downloads, le dossier NG659C1_11_09_2018_09_16_47_treatment_resource est créé, mais le dossier A350_TRT_047 n'est pas créé, alors qu'il le devrait. C'est un fichier qui créé à la place. Donc forcément lorsque il essait d'y mettre le dossier CRDC_A01, il ne peut pas.

    Cette archive n'est pas corrompue, mais elle doit avoir des propriétés spécifiques qui font que le module zipfile de python échoue. Si j'extracte avec 7zip ou Winrar. il n'y pas de problème.
    Mon code python est correct car si je re-zip avec 7zip ou Winrar le résultat de l'extraction, mon code python arrive à décompresser correctement l'archive.

  2. #2
    Expert éminent
    Avatar de tyrtamos
    Homme Profil pro
    Retraité
    Inscrit en
    Décembre 2007
    Messages
    4 462
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2007
    Messages : 4 462
    Points : 9 249
    Points
    9 249
    Billets dans le blog
    6
    Par défaut
    Bonjour,

    Le module zipfile possède pas mal de possibilités de vérification d'une archive.

    Voilà un petit code à moi pour afficher seulement les noms des fichiers de l'archive (sans enregistrer leur contenu!):

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    def listezip(fichierzip):
        """affiche la liste des fichiers de l'archive
        """
        if zipfile.is_zipfile(fichierzip):
            try:
                with zipfile.ZipFile(fichierzip) as fzip:
                    for fichier in fzip.namelist():
                        if fichier[0] in "\\/" or fichier[1]==":":
                            print("Danger: chemin absolu =>", fichier) 
                        else:
                            print(fichier)
            except Exception as msgerr:
                print("Erreur =>", msgerr)
        else:
            print("Ce fichier n'est pas une archive zip valide")
    Ce petit code permet, en particulier, de détecter les archives qui ont un chemin absolu, ce qui constitue un danger si l'archive a une origine pas sûre.


    On peut aller plus loin dans la recherche des infos d'archivage de chacun des fichiers de l'archive:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    def infozip(fichierzip):
     
        compress_type = {0:"ZIP_STORED", 8:"ZIP_DEFLATED", 12:"ZIP_BZIP2", 14:"ZIP_LZMA"}
     
        if zipfile.is_zipfile(fichierzip):
            with zipfile.ZipFile(fichierzip) as fzip:
                for fichier in fzip.namelist():
                    print("="*78)
                    info = fzip.getinfo(fichier)
                    print(info.filename)
                    print()
                    print("date_time:", info.date_time)
                    print("compress_type:", compress_type[info.compress_type]) 
                    print("comment:", info.comment) 
                    print("extra:", info.extra) 
                    print("create_system:", info.create_system) 
                    print("create_version:", info.create_version) 
                    print("extract_version:", info.extract_version) 
                    print("reserved:", info.reserved) 
                    print("flag_bits:", info.flag_bits) 
                    print("volume:", info.volume) 
                    print("internal_attr:", info.internal_attr) 
                    print("info.external_attr:", info.external_attr) 
                    print("header_offset:", info.header_offset)
                    print("CRC:", info.CRC) 
                    print("compress_size:", info.compress_size)
                    print() 
     
        else:
            print("Ce fichier n'est pas une archive zip valide")
    Pour avoir plus d'information sur l'archivage, il y a pas mal d'infos ici: https://pkware.cachefly.net/webdocs/...es/APPNOTE.TXT


    Enfin, au lieu de extractall, on peut utiliser extract fichier par fichier, ce qui permettrait de savoir quel est celui qui déclenche l'exception:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    def extraitzip(fichierzip, repdest, motdepasse=None):
        """Extrait l'archive zip dans le répertoire destination repdest
           Suppose que les chemins de l'archive sont relatifs
           (danger s'ils sont absolus et si origine de l'archive non sûre)
        """
        if zipfile.is_zipfile(fichierzip):
            with zipfile.ZipFile(fichierzip, "r") as fzip:
                for fichier in fzip.namelist():
                    try:
                        fzip.extract(fichier, repdest, motdepasse)
                        print("Extraction de", fichier) 
                    except Exception as msgerr:
                        print("Erreur =>", msgerr)
        else:
            print("Ce fichier", fichierzip, "n'est pas une archive valide" )
    Dans ces 3 fonctions, j'ai supposé que les chemins contenus dans l'archive sont relatifs. Je n'ai pas prévu le cas où ils pourraient être absolus.

    Essaie tout ça, et dis si tu trouves l'origine de ton pb.

    [Edit]: désolé, c'est du Python 3 (je n'ai plus Python 2 depuis longtemps). Mais le principe devrait rester valable: à convertir.
    Un expert est une personne qui a fait toutes les erreurs qui peuvent être faites, dans un domaine étroit... (Niels Bohr)
    Mes recettes python: http://www.jpvweb.com

  3. #3
    Membre régulier
    Homme Profil pro
    Ingénieur validation
    Inscrit en
    Juin 2012
    Messages
    89
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingénieur validation
    Secteur : High Tech - Matériel informatique

    Informations forums :
    Inscription : Juin 2012
    Messages : 89
    Points : 70
    Points
    70
    Par défaut
    Merci. J'ai utilisé tes lignes de code pour comparer l'archive que je télécharge avec l'archive que je créé à partir des fichiers extraits.

    Dans l'archive que je télécharge, il manque les '/' à la fin des nom de dossier à créer. Donc zipfile crée un fichier au lieu de créer un dossier:

    Extrait de la sortie de listezip() avec l'archive téléchargée:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    listezip('_NG67EC9_treatment_resource_DL.zip')
    NG67EC9_01_10_2018_11_58_36_treatment_resource/
    NG67EC9_01_10_2018_11_58_36_treatment_resource/A350_TRT_048
    NG67EC9_01_10_2018_11_58_36_treatment_resource/A350_TRT_048/CRDC_A01
    ...
    Extrait de la sortie de listezip() avec l'archive reconstituée:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    listezip('NG67EC9_treatment_resource_Rezip.zip')
    NG67EC9_01_10_2018_11_58_36_treatment_resource/
    NG67EC9_01_10_2018_11_58_36_treatment_resource/A350_TRT_048/
    NG67EC9_01_10_2018_11_58_36_treatment_resource/A350_TRT_048/CRDC_A01/
    ...
    fichiers complets:infozip_et_listezip.zip

    Mais bon les logiciels comme 7zip arrivent à décoder l'arborescence de l'archive....

  4. #4
    Expert éminent
    Avatar de tyrtamos
    Homme Profil pro
    Retraité
    Inscrit en
    Décembre 2007
    Messages
    4 462
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2007
    Messages : 4 462
    Points : 9 249
    Points
    9 249
    Billets dans le blog
    6
    Par défaut
    Bonjour,

    Effectivement:
    - quand 7-zip crée une nouvelle archive à partir d'un répertoire donné, il ajoute les sous-répertoires avec un "/" à la fin.
    - il en est de même quand on crée une nouvelle archive avec le module zipfile de Python

    Le problème, c'est que quand on extrait les fichiers de l'archive, on ne peut pas distinguer les "vrais" fichiers des sous-répertoires non terminés par "/"!

    Manifestement, l'archive que tu as téléchargée n'a pas été correctement construite.

    Je te propose le contournement suivant:

    Dans le code Python d'extraction que je t'ai proposé (extraitzip), à chaque fichier de la fzip.namelist(), tu vas tester fzip.getinfo(fichier).compress_size, et tu vas considérer que si c'est égal à zéro, c'est un sous-répertoire! Ceci en supposant que ton archive n'a pas de fichier de taille=0. Il suffira alors de ne pas demander l'extraction du sous-répertoire.

    Cela donnerait une fonction d'extraction comme ça:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    def extraitzip(fichierzip, repdest, motdepasse=None):
        """Extrait l'archive zip dans le répertoire destination repdest
           Suppose que les chemins de l'archive sont relatifs
           (danger s'ils sont absolus et si origine de l'archive non sûre)
        """
        if zipfile.is_zipfile(fichierzip):
            with zipfile.ZipFile(fichierzip, "r") as fzip:
                for fichier in fzip.namelist():
     
                    if fzip.getinfo(fichier).compress_size==0:
                        continue
     
                    try:
                        fzip.extract(fichier, repdest, motdepasse)
                        print("Extraction de", fichier) 
                    except Exception as msgerr:
                        print("Erreur =>", msgerr)
        else:
            print("Ce fichier", fichierzip, "n'est pas une archive valide" )
    Essaie!

    Et pour compléter les codes concernant les archives zip, voilà celui qui permet de créer une archive zip à partir du contenu d'un répertoire donné:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    def creazip(repertoire, fichierzip):
        """Crée une nouvelle archive zip contenant tous les fichiers et 
             sous-répertoires du répertoire donné.
           Les chemins enregistrés sont tous relatifs, et commencent par
             le dernier nom de répertoire du répertoire donné 
        """
        fichierzip = os.path.abspath(fichierzip)
        baserep = os.path.dirname(os.path.abspath(os.path.expanduser(repertoire)))
        with zipfile.ZipFile(fichierzip, "w") as fzip:
            for repert, sreperts, fichiers in os.walk(repertoire):
                # ajout au fichier zip
                fzip.write(repert, os.path.relpath(repert, baserep))
                for fichier in fichiers:
                    # chemin absolu du fichier
                    fichierabs = os.path.join(repert, fichier)
                    # ajout au fichier zip
                    fzip.write(fichierabs, os.path.relpath(fichierabs, baserep))
    Tu peux voir comment on obtient les adresses relatives avec relpath, et comment on l'enregistre dans l'archive: en utilisant le fait que fzip.write permet 2 arguments: 1er=l'adresse absolu, et 2ème=l'adresse relative à intégrer dans l'archive.
    Un expert est une personne qui a fait toutes les erreurs qui peuvent être faites, dans un domaine étroit... (Niels Bohr)
    Mes recettes python: http://www.jpvweb.com

Discussions similaires

  1. [Python 3.X] FileNotFoundError: [Errno 2] No such file or directory
    Par F6AAP dans le forum Général Python
    Réponses: 0
    Dernier message: 17/03/2017, 19h49
  2. list : no such file or directory :(
    Par Bakura dans le forum C++
    Réponses: 23
    Dernier message: 13/06/2006, 16h30
  3. Réponses: 7
    Dernier message: 26/04/2006, 09h56
  4. Réponses: 3
    Dernier message: 16/01/2006, 18h24
  5. Réponses: 1
    Dernier message: 04/10/2005, 20h01

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo