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 :

Problème avec glob


Sujet :

Python

  1. #1
    Membre éprouvé

    Profil pro
    Account Manager
    Inscrit en
    Décembre 2006
    Messages
    2 301
    Détails du profil
    Informations personnelles :
    Localisation : France, Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : Account Manager

    Informations forums :
    Inscription : Décembre 2006
    Messages : 2 301
    Par défaut Problème avec glob
    Bonjour,
    le code ci-dessous bloque. Pourquoi ?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    import glob
    cheminTeste = "C:\\Documents and Settings\\Christophe\\Mes documents\\3,Codes Programmes v-3 Fev 2009\\Python\\Veusz [Donnees-PyQt]\\*"
    thisDir = glob.iglob(cheminTeste)
    for onePath in thisDir:  
        print onePath
    Le message d'erreur est le suivant :
    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
    Traceback (most recent call last):
      File "C:\Documents and Settings\Christophe\Mes documents\2,pyBaNaMa\CodeSource\packages\GestionCheminFichiers.py", line 31, in <module>
        lectureDossier(os.path.join('C:\\Documents and Settings\\Christophe\\Mes documents\\3,Codes Programmes v-3 Fev 2009\\Python\\Veusz [Donnees-PyQt]', '*'))
      File "C:\Documents and Settings\Christophe\Mes documents\2,pyBaNaMa\CodeSource\packages\GestionCheminFichiers.py", line 15, in lectureDossier
        for onePath in thisDir:  
      File "C:\Python26\lib\glob.py", line 41, in iglob
        for dirname in dirs:
      File "C:\Python26\lib\glob.py", line 42, in iglob
        for name in glob_in_dir(dirname, basename):
      File "C:\Python26\lib\glob.py", line 61, in glob1
        return fnmatch.filter(names, pattern)
      File "C:\Python26\lib\fnmatch.py", line 47, in filter
        _cache[pat] = re.compile(res)
      File "C:\Python26\lib\re.py", line 188, in compile
        return _compile(pattern, flags)
      File "C:\Python26\lib\re.py", line 243, in _compile
        raise error, v # invalid expression
    sre_constants.error: bad character range
    Je ne vois pas trop le caractère qui pourrait poser problème. Si quelqu'un a une idée...

  2. #2
    Membre éprouvé

    Profil pro
    Account Manager
    Inscrit en
    Décembre 2006
    Messages
    2 301
    Détails du profil
    Informations personnelles :
    Localisation : France, Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : Account Manager

    Informations forums :
    Inscription : Décembre 2006
    Messages : 2 301
    Par défaut
    En fait, ce sont les crochets qui posent problème. Qui peut-on contacter pour indiquer le souci s'il n'est pas contournable ? Pour moi il y en a un dans la mesure où ce type de caractères est accepté sous Windows.

  3. #3
    Membre émérite
    Avatar de Antoine_935
    Profil pro
    Développeur web/mobile
    Inscrit en
    Juillet 2006
    Messages
    883
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations professionnelles :
    Activité : Développeur web/mobile

    Informations forums :
    Inscription : Juillet 2006
    Messages : 883
    Par défaut
    Commence par échapper les crochets ouvrants avec des backslashes.

  4. #4
    Membre éprouvé

    Profil pro
    Account Manager
    Inscrit en
    Décembre 2006
    Messages
    2 301
    Détails du profil
    Informations personnelles :
    Localisation : France, Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : Account Manager

    Informations forums :
    Inscription : Décembre 2006
    Messages : 2 301
    Par défaut
    Le souci est que ce chemin m'est donné par le module os et du coup il y a à mes yeux un gros souci de cohérence. Non ?

    J'ai essayé ta proposition sans succès.

  5. #5
    Membre émérite
    Avatar de Antoine_935
    Profil pro
    Développeur web/mobile
    Inscrit en
    Juillet 2006
    Messages
    883
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations professionnelles :
    Activité : Développeur web/mobile

    Informations forums :
    Inscription : Juillet 2006
    Messages : 883
    Par défaut
    Il y aurait, à mon goût, un souci de cohérence si les fonctions de globbing faisaient partie du module os. Ce n'est pas le cas, donc je trouve ces différences acceptables.

    De quelle manière as-tu échappé les crochets ? De ce que je lis du message d'erreur
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    sre_constants.error: bad character range
    Il y a une erreur dans le parsing du character range, soit justement la classe de caractère entre les deux crochets, qui contient deux fois les lettres n et e. Il peut aussi s'agir du s-P, et je crois même que l'erreur est ici.

    Fais nous voir la chaîne échappée.

  6. #6
    Membre Expert
    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    1 418
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 1 418
    Par défaut
    glob

    The glob module finds all the pathnames matching a specified pattern according to the rules used by the Unix shell.


    fnmatch

    This module provides support for Unix shell-style wildcards, which are not the same as regular expressions.

    Dans les expressions régulières, il y a deux manières d’échapper un caractère spécial: avec ’\’ ou avec ’[ ]’ puisque «Special characters are not active inside sets.» et que '[[]' échappe le crochet gauche.
    http://www.python.org/doc/2.5.2/lib/re-syntax.html

    \’ est d’ailleurs plus universel puisque ’[g\d]’ ou '[kl9\]' n’échappent pas le ’\’ en leur sein. Dans le deuxième cas, cela produit une erreur (la Library Reference oublie de le préciser soit dit en passant).


    Dans les pathnames, obéissant aux règles du shell Unix, il ne reste plus que 5 caractères spéciaux et une seule manière de les échapper: ’[ ]’.
    The special characters used in shell-style wildcards are:
    * matches everything
    ? matches any single character
    [seq] matches any character in seq
    [!seq] matches any character not in seq
    http://www.python.org/doc/2.5.2/lib/....html#l2h-2288

    D’où ma proposition:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    ......\\Python\\Veusz [[]Donnees-PyQt]\\*"
    Inutile d’échapper le crochet droit:
    le crochet gauche n’étant plus un crochet d’ouverture d’un set ==> le crochet droit n’est plus interprété comme un caractère spécial de fermeture de set.



    NB:
    à mon avis, doubler les ’\’ dans ton chemin ne sert à rien, il ne comporte aucune séquence spéciale du genre ’\a',’\b’,’\f’ etc.


    PS:
    Je pense que le message d’erreur que tu obtiens est dû au fait que le programme interprète [Donnees-PyQt] comme un ensemble contenant les lettres ’D’,’o’,’n’,’e’,’y’,’Q’,’t’ et le range ’s-P’.

    Seulement, ’s’ est minuscule et ’P’ est majuscule, et de plus ’p’ est avant ’s’ dans l’alphabet. Donc le programme ne comprend pas le range “indiqué“.

  7. #7
    Membre émérite
    Avatar de Antoine_935
    Profil pro
    Développeur web/mobile
    Inscrit en
    Juillet 2006
    Messages
    883
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations professionnelles :
    Activité : Développeur web/mobile

    Informations forums :
    Inscription : Juillet 2006
    Messages : 883
    Par défaut
    Les regex python répondent aux standards quant aux échappements des caractères. C'est à dire qu'il suffit de précéder les métacaractères par un backslash pour les échapper. De plus, ces métacaractères n'ont plus leur signification spéciale dans une classe (entre crochets). Ils sont considérés en temps que tels.

    Citation Envoyé par eyquem Voir le message
    D’où ma proposition:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    ......\\Python\\Veusz [[]Donnees-PyQt]\\*"
    Voila de quoi rendre une regex bien illisible. Je n'ai pas de python sous la main, mais échapper le premier crochet peut se faire avec un \
    Bien entendu, puisque nous sommes dans une string, il faut également doubler le backslash. D'où l'intérêt de se servir des rawstring
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    pattern = '\\[Donnees-Python]'
    # ou encore
    pattern = r'\[Donnees-Python]'

  8. #8
    Membre éprouvé

    Profil pro
    Account Manager
    Inscrit en
    Décembre 2006
    Messages
    2 301
    Détails du profil
    Informations personnelles :
    Localisation : France, Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : Account Manager

    Informations forums :
    Inscription : Décembre 2006
    Messages : 2 301
    Par défaut
    Merci à tous les deux.

    Citation Envoyé par Antoine_935 Voir le message
    Il y aurait, à mon goût, un souci de cohérence si les fonctions de globbing faisaient partie du module os. Ce n'est pas le cas, donc je trouve ces différences acceptables.
    Oui effectivement et en fait c'est moi qui n'ai pas été cohérent en utilisant os et glob. Le mieux est en fait de faire comme suit :
    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
    #!/usr/bin/env python
    #coding=utf-8
     
    import os
     
    def lectureDossier(cheminTeste):
        thisDir = os.listdir(cheminTeste)
     
        for onePath in thisDir:  
            onePath = os.path.join(cheminTeste,onePath)
            if os.path.isdir(os.path.join(cheminTeste,onePath)):
                print 'DOSSIER : ' + str(onePath)
                lectureDossier(onePath)
            else:
                print '\tFICHIER : ' + str(onePath)
     
    #lectureDossier(os.path.expanduser('~'))
    lectureDossier('C:/Documents and Settings/Christophe/Mes documents/3,Codes Programmes v-3 Fev 2009/Python/Veusz [Donnees-PyQt]')
    Citation Envoyé par eyquem Voir le message
    D’où ma proposition:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    ......\\Python\\Veusz [[]Donnees-PyQt]\\*"
    Cela marche sans souci.

    Citation Envoyé par Antoine_935 Voir le message
    Bien entendu, puisque nous sommes dans une string, il faut également doubler le backslash. D'où l'intérêt de se servir des rawstring
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    pattern = '\\[Donnees-Python]'
    # ou encore
    pattern = r'\[Donnees-Python]'
    Etant sous Windows, je ne peux pas utiliser cette méthode car '\' sert à repérer les dossiers.

    En conclusion, il semblerait que glob soit moins pratique à utiliser que os qui est multi-plateforme sans souci. Par contre, glob semble être utile pour avoir des fichiers d'un type donné contrairement à os avec lequel on doit faire la recherche soit même.

  9. #9
    Membre Expert
    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    1 418
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 1 418
    Par défaut
    Je ne m’étais encore jamais intéressé de près aux problèmes de noms de chemins jusqu’à présent, je ne suis donc pas encore très au courant, certes. Mais dîtes moi où je me trompe dans ce qui suit:


    J’ai décortiqué, non sans mal, le message d’erreur donné par rambc.

    Les 4 lignes

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
      File "C:\Python26\lib\re.py", line 188, in compile
        return _compile(pattern, flags)
      File "C:\Python26\lib\re.py", line 243, in _compile
        raise error, v # invalid expression
    signalent que le module re.py a du mal à déduire un regex object de l’expression qui lui est passée.

    Les 4 lignes

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
      File "C:\Python26\lib\glob.py", line 61, in glob1
        return fnmatch.filter(names, pattern)
      File "C:\Python26\lib\fnmatch.py", line 47, in filter
        _cache[pat] = re.compile(res)
    informent que c’est dans la fonction filter() du module fnmatch.py qu’il est fait appel au module re.py pour calculer la valeur de _cache[pat].

    En fouillant dans le module fnmatch.py, on voit que l’expession res qui est passée à re.compile() est obtenue en faisant agir la fonction translate() du module fnmatch.py sur une variable pat. Je n’ai pas examiné à la loupe comment ça se passe avant pat, mais un coup d’œil même superficiel montre que pat est le nom de chemin qui est passé à la fonction glob.iglob(), c’est à dire dans notre cas l’expression représentée par la chaîne cheminTeste.



    Or le commentaire de fnmatch.translate() est:

    """Translate a shell PATTERN to a regular expression.

    There is no way to quote meta-characters.
    """


    je ne comprends pas la seconde phrase mais la première signifie que fnmatch.translate() traite l’argument qui lui est passé en le considérant comme un «shell PATTERN».

    Pour écrire le nom de chemin qui est passé à glob.iglob() donc à fnmatch.translate(), on ne peut donc pas faire autrement que de le faire en tenant compte des spécifications qui régissent les «shell PATTERN». Il faut alors fouiller un peu pour trouver ces règles, «which are not the same as regular expressions.» Ce n’est pas moi qui le dis.

    À partir de là, je ne pourrais que répéter mon précédent message.



    Je signale quand même que j’ai fait tourner le code:

    que ce soit avec '\\[Donnees-Python]' ou

    r'\[Donnees-Python]' ou

    '\\[Donnees-Python\\]' ou

    r'\[Donnees-Python\]' ,

    on n’obtient plus d’erreur, mais le problème est que le programme ne sort pas les noms de fichiers et dossiers contenus dans \\Python\\Veusz [Donnees-PyQt]
    c’est à dire que le code donne un mauvais résultat.

    En fait, je ne comprends pas pourquoi l’ajout de ’\\’ devant le crochet gauche fait cesser l’erreur; je ne me suis pas suffisamment plongé dans cette question.
    Mais le fait est que ce n’est qu’en utilisant le seul moyen d’échapper les caractères spéciaux des «shell patterns» que j’obtiens le bon résultat, sur mon ordinateur : ’[[]’



    Erratum:

    J’ai écrit trop vite:
    «à mon avis, doubler les ’\’ dans ton chemin ne sert à rien, il ne comporte aucune séquence spéciale du genre ’\a',’\b’,’\f’ etc.»
    dans
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    "C:\Documents and Settings\Christophe\Mes documents\3,Codes Programmes v-3 Fev 2009\Python\Veusz [Donnees-PyQt]\*"
    il y a ’\V’ qui est lu par fnmatch.py comme ’\v’ c’est à dire une séquence spéciale.
    Il faut donc mettre Python\\Veusz [Donnees-PyQt]\*"
    ou utiliser une raw string.



    PS
    Etant sous Windows, je ne peux pas utiliser cette méthode car '\' sert à repérer les dossiers.
    Je ne vois pas en quoi ça constitue un problème. La raison de ne pas utiliser de backslash pour résoudre ton problème n’est pas là. À mon avis. Donne un problème avec les backslashes dans Windows et on verra si on n'arrive pas à le résoudre.




    Je tire une conclusion de cet intéressant problème:

    de même que les arguments qui sont passés à re.compile() ne sont pas des chaînes mais des expressions régulières, les arguments qui sont passés à glob.iglob() ne sont pas des chaînes mais des shell expressions.

  10. #10
    Membre éprouvé

    Profil pro
    Account Manager
    Inscrit en
    Décembre 2006
    Messages
    2 301
    Détails du profil
    Informations personnelles :
    Localisation : France, Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : Account Manager

    Informations forums :
    Inscription : Décembre 2006
    Messages : 2 301
    Par défaut
    Comme os me convient parfaitement, je vais laisser de côté le module glob.
    Citation Envoyé par eyquem Voir le message
    Mais le fait est que ce n’est qu’en utilisant le seul moyen d’échapper les caractères spéciaux des «shell patterns» que j’obtiens le bon résultat, sur mon ordinateur : ’[[]’
    Je confirme...

    Citation Envoyé par eyquem Voir le message
    Je ne vois pas en quoi ça constitue un problème. La raison de ne pas utiliser de backslash pour résoudre ton problème n’est pas là. À mon avis. Donne un problème avec les backslashes dans Windows et on verra si on n'arrive pas à le résoudre.
    En fait, ce que je voulais dire c'est qu'en utilisant les backslash, cela ne fonctionne pas.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Problème avec glob sur un disque externe
    Par rambc dans le forum Général Python
    Réponses: 11
    Dernier message: 16/01/2010, 10h22
  2. [PERL] Problème d'espace avec glob()
    Par sephiburp dans le forum Programmation et administration système
    Réponses: 2
    Dernier message: 11/06/2009, 14h49
  3. Réponses: 1
    Dernier message: 07/02/2008, 21h40
  4. Problème avec la mémoire virtuelle
    Par Anonymous dans le forum CORBA
    Réponses: 13
    Dernier message: 16/04/2002, 16h10

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