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 :

Fonction enumerate et encoding


Sujet :

Python

  1. #1
    Membre averti
    Profil pro
    Inscrit en
    Avril 2006
    Messages
    20
    Détails du profil
    Informations personnelles :
    Âge : 47
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Avril 2006
    Messages : 20
    Par défaut Fonction enumerate et encoding
    Bonjour,
    J'utilisais dans mon code la ligne suivante:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    for i,row in enumerate(filename):
    filename est un fichier (dans mon cas le type exact est InMemoryUploadedFile car c'est dans Django, mais cela ne change rien)

    Mais je me rends compte que cela ne fonctionne qu'avec certains types d'encodages. Par exemple, cela ne fonctionne pas lorsque le fichier est en UTF_16_LE ou UTF_16_BE. Comment modifier le code pour qu'il fonctionne dans ces cas-là (sachant que je connais l'encoding à l'avance)? Merci!

  2. #2
    Expert éminent
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 715
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Manche (Basse Normandie)

    Informations professionnelles :
    Activité : Architecte technique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2008
    Messages : 21 715
    Par défaut
    Salut,

    enumerate se contente d'un iterable.
    Un objet de type "file" en est un - çà tombe bien - mais pour ce qui est de son "encoding", çà se fait "ailleurs" et "avant" (à l'open par exemple ou en le précisant à InMemoryUploadedFile). On peut bien sur imaginer que l'objet de type "file" ait été ouvert en "binaire" et qu'on veuille le décoder à la lecture.
    Exemple test.txt est un fichier contenant 'éééé\nùùù\naaa\n' codé en "latin-1":
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    >>> f = open('test.txt', 'rb')
    >>> f.read()
    b'\xe9\xe9\xe9\xe9\r\n\xf9\xf9\xf9\r\naaa\r\n'
    Si on veut "décoder":
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    >>> import codecs
    >>> f2=codecs.getreader('latin-1')(f)
    >>> f.seek(0)
    0
    >>> f2.read()
    'éééé\r\nùùù\r\naaa\r\n'
    - W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

  3. #3
    Membre averti
    Profil pro
    Inscrit en
    Avril 2006
    Messages
    20
    Détails du profil
    Informations personnelles :
    Âge : 47
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Avril 2006
    Messages : 20
    Par défaut
    Il me semble cependant que la fonction enumerate appliquée sur un objet fichier appelle la méthode open de Python, qui utilise par défaut le codage UTF-8 et est peut-être compatible avec d'autres encodages. Je n'avais besoin de faire aucune manipulation/ouverture sur le fichier avant l'appel à enumerate. L'objet fichier était obtenu directement à partir de self.request.FILES en Django.

    Avec la ligne suivante, mon code était:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    for i,row in enumerate(filename):
      row_decode=row.decode(encoding, errors='ignore')
    L'idéal aurait été que la fonction enumerate puisse prendre un paramètre encoding pour conserver la même logique. D'après la réponse précédente il me semble que je peux utiliser codecs.getreader pour obtenir un nouvel objet fichier sur lequel appliquer enumerate. Ou sinon faire le travail à la main: récupération de la chaîne de caractères en utilisant le bon encoding, remplacement des caractères fin de ligne, split pour obtenir un tableau, puis enumerate sur le tableau.

  4. #4
    Expert éminent
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 715
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Manche (Basse Normandie)

    Informations professionnelles :
    Activité : Architecte technique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2008
    Messages : 21 715
    Par défaut
    Citation Envoyé par GnarlyYoyo Voir le message
    Il me semble cependant que la fonction enumerate appliquée sur un objet fichier appelle la méthode open de Python, qui utilise par défaut le codage UTF-8 et est peut-être compatible avec d'autres encodages.
    Si tel était le cas, ce serait documenté et vous pourriez coder un exemple simple montrant que çà fonctionne bien comme çà...

    Citation Envoyé par GnarlyYoyo Voir le message
    Je n'avais besoin de faire aucune manipulation/ouverture sur le fichier avant l'appel à enumerate. L'objet fichier était obtenu directement à partir de self.request.FILES en Django.

    Avec la ligne suivante, mon code était:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    for i,row in enumerate(filename):
      row_decode=row.decode(encoding, errors='ignore')
    L'idéal aurait été que la fonction enumerate puisse prendre un paramètre encoding pour conserver la même logique. D'après la réponse précédente il me semble que je peux utiliser codecs.getreader pour obtenir un nouvel objet fichier sur lequel appliquer enumerate. Ou sinon faire le travail à la main: récupération de la chaîne de caractères en utilisant le bon encoding, remplacement des caractères fin de ligne, split pour obtenir un tableau, puis enumerate sur le tableau.
    En informatique, chaque primitive comme "enumerate", "open", ... se contente de réaliser un minimum d"opérations sur un objet que vous allez pouvoir composer après avoir construit des exemples reflétant les cas d'utilisation que vous voulez réaliser.
    Un truc comme:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    for i,row in enumerate(filename):
      row_decode=row.decode(encoding, errors='ignore')
    est probablement une grosse erreur: si vous connaissez l'encoding, il ne devrait pas y avoir d'erreur. Dans le cas contraire, çà peut faire des choses que vous ne vouliez pas vraiement. Exemple toujours avec mon fichier bidon codé latin-1 et ouvert en binaire:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    >>> f.seek(0)
    0
    >>> f.read()
    b'\xe9\xe9\xe9\xe9\n\xf9\xf9\xf9\naaa\n'
    Si je décode avec un mauvais encoding en ignorant les erreurs:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    >>> f.seek(0)
    0
    >>> f.read().decode('utf-8', errors='ignore')
    '\n\naaa\n'
    >>>
    => çà vire tous les caractères accentués.

    Problème que l'on n'a pas avec le "bon encoding":
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    >>> f.seek(0)
    0
    >>> f.read().decode('latin-1', errors='ignore')
    'éééé\nùùù\naaa\n'
    >>>
    In fine, vous pouvez obtenir un code qui ne plante pas mais si vous ne vérifiez rien, bonjour les dégâts.

    note: et rien ne vous empêche de "composer":
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    for i, row in enumerate(filename.read().decode(encoding).splitlines()):
         ...
    ou bien:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    for i, row in enumerate(codecs.getreader(encoding)(filename).read().splitlines()):
         ...
    ou de décomposer:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    lines = filename.read().decode(encoding).splitlines()
    for i, row in enumerate(lines):
         ...
    - W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

  5. #5
    Membre averti
    Profil pro
    Inscrit en
    Avril 2006
    Messages
    20
    Détails du profil
    Informations personnelles :
    Âge : 47
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Avril 2006
    Messages : 20
    Par défaut
    Merci, cela fonctionne.

    Le code suivant peut encore se simplifier:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    for i, row in enumerate(codecs.getreader(encoding)(filename).read().splitlines()):
         ...

    devient:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    for i,row in enumerate(codecs.getreader(encoding)(filename)):
         ...
    puisque le comportement de la fonction enumerate sur un object fichier correspond à .read().splitlines()

  6. #6
    Expert éminent
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 715
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Manche (Basse Normandie)

    Informations professionnelles :
    Activité : Architecte technique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2008
    Messages : 21 715
    Par défaut
    Citation Envoyé par GnarlyYoyo Voir le message
    puisque le comportement de la fonction enumerate sur un object fichier correspond à .read().splitlines()
    non car si vous écrivez "for line in filename", line contiendra la fin de ligne.
    Or vous vouliez:
    Citation Envoyé par GnarlyYoyo Voir le message
    L'idéal aurait été que la fonction enumerate puisse prendre un paramètre encoding pour conserver la même logique. D'après la réponse précédente il me semble que je peux utiliser codecs.getreader pour obtenir un nouvel objet fichier sur lequel appliquer enumerate. Ou sinon faire le travail à la main: récupération de la chaîne de caractères en utilisant le bon encoding, remplacement des caractères fin de ligne, split pour obtenir un tableau, puis enumerate sur le tableau.
    Et comme votre fichier ressemble à un fichier CSV, vous pourriez faire faire une grosse partie du boulot par le module CSV.

    - W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

Discussions similaires

  1. Encoder un tableau PHP en JSON qui contient des fonctions JS
    Par Spartacusply dans le forum Langage
    Réponses: 2
    Dernier message: 11/09/2014, 12h07
  2. liste et fonction enumerate
    Par Sbmnt dans le forum Général Python
    Réponses: 3
    Dernier message: 08/07/2013, 21h31
  3. UTF8-Encode ne marche pas avec la fonction "Filter"
    Par messahel dans le forum Bases de données
    Réponses: 8
    Dernier message: 17/10/2011, 10h57
  4. Fonction qui encode les URLs
    Par khayyam90 dans le forum Contribuez
    Réponses: 0
    Dernier message: 09/02/2011, 22h21
  5. Enumerer la liste des parametres d'une fonction
    Par themadmax dans le forum C#
    Réponses: 10
    Dernier message: 01/04/2008, 15h13

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