Partage
  • Partager sur Facebook
  • Partager sur Twitter

caractères spéciaux

    6 octobre 2012 à 19:22:59

    bonjour bonjour,
    voila, j'ai cherché un petit peu partout, sans trouver de réponse qui me convienne, donc je me permets de poser la question ici
    J'ai fait un petit programme en python, qui récupère de temps en temps du texte entré par l'utilisateur.
    J'aimerai donc savoir la méthode communément utilisée pour gérer ce genre de soucis, à savoir convertir tous les 'é' en 'e', les 'à' en 'a', remplacer les signes de ponctuation par des underscore, etc etc.

    J'avais souvenir d'un truc du genre une ligne au début du fichier où on crée deux variables avec toutes les lettes à remplacer et une autre avec toutes les lettres de remplacement... Ca dit quelque chose à quelqu'un ? ça existe, ou je l'ai juste inventé ? ^^

    Bref voila, merci de m'éclairer quant à la méthode à utiliser pour gérer ce genre de soucis !
    • Partager sur Facebook
    • Partager sur Twitter
      6 octobre 2012 à 21:28:09

      Va voir du coté str.maketrans et str.tanslate.
      • Partager sur Facebook
      • Partager sur Twitter
        6 octobre 2012 à 23:30:37

        Citation : fruity'

        J'aimerai donc savoir la méthode communément utilisée pour gérer ce genre de soucis



        quel souci ?
        • Partager sur Facebook
        • Partager sur Twitter

        Python c'est bon, mangez-en. 

        Anonyme
          7 octobre 2012 à 9:24:29

          Bonjour,

          Dès qu'on veut traiter des chaines de caractères comportant des accents, on a un gros problème à traiter: celui de l'encodage. Si on s'y prend mal, cela risque même de planter un programme. D'où les précautions dans les codes suivants.

          Je te propose 2 solutions (Python 2.7) pour retirer les accents sans changer la casse (les minuscules restent des minuscules, idem pour les majuscules).

          1ère solution: remplacement caractère par caractère:

          def sansaccent(ch, encod='utf-8'):
              """Supprime les accents sans changer la casse (majuscules et minuscules)"""
              conv = False
              if not isinstance(ch, unicode):
                  ch = unicode(ch, encod, 'replace')
                  conv = True
              alpha1 = u"àÀâÂäÄåÅçÇéÉèÈêÊëËîÎïÏôÔöÖùÙûÛüÜÿŸ"
              alpha2 = u"aAaAaAaAcCeEeEeEeEiIiIoOoOuUuUuUyY"
              x = ""
              for c in ch:
                  k = alpha1.find(c)
                  if k >= 0:
                      x += alpha2[k]
                  else:
                      x += c
              if conv:
                  x = x.encode(encod)
              return x
          


          Le traitement est toujours fait en unicode. Si la chaine passée en argument est en unicode, elle est traitée et le résultat est retourné en unicode. Si par contre elle n'est pas en unicode, il faut donner son encodage ('utf-8' par défaut) et le résultat sera retourné dans le même encodage.

          Petit complément: si on a une page de code démarrée par une ligne comme "# -*- coding: utf-8 -*-", cela indique à Python que toutes les chaines "codées en dur" sur la page sont en 'utf-8'. Et si elle sont codées avec u"...", elle seront convertis en unicode.

          Exemple de chaines passées en unicode

          chaine = u"àÀâÂäÄåÅçÇéÉèÈêÊëËîÎïÏôÔöÖùÙûÛüÜÿŸ"
          
          print chaine
          àÀâÂäÄåÅçÇéÉèÈêÊëËîÎïÏôÔöÖùÙûÛüÜÿŸ <= cette chaine est en encodage unicode
          
          print sansaccent(chaine)
          aAaAaAaAcCeEeEeEeEiIiIoOoOuUuUuUyY <= cette chaine est en encodage unicode
          


          Exemple de chaine passée en encodage 'latin1':

          chaine = u"àÀâÂäÄåÅçÇéÉèÈêÊëËîÎïÏôÔöÖùÙûÛüÜ".encode('latin1')
          
          print chaine
          àÀâÂäÄåÅçÇéÉèÈêÊëËîÎïÏôÔöÖùÙûÛüÜ <= cette chaine est en encodage 'latin1'
          
          print sansaccent(chaine, 'latin1')
          aAaAaAaAcCeEeEeEeEiIiIoOoOuUuUuU <= cette chaine est en encodage 'latin1'
          


          Petite différence entre les 2 chaines d'essai: les caractères 'ÿ' et 'Ÿ' sont des caractères français, bien que rares (L’Haÿ-les-Roses: Val-de-Marne), mais n'existent pas dans l'encodage 'latin1'.

          2e solution: utilisation du module unicodedata

          On utilise le fait que les caractères unicode ont une codification qui permet de séparer les caractères de base et leur accent éventuel.

          import unicodedata
          
          def sansaccent(ch, encod='utf-8'):
              """Supprime les accents sans changer la casse (majuscules et minuscules)"""
              conv = False
              if not isinstance(ch, unicode):
                  ch = unicode(ch, encod,'replace')
                  conv = True
              chnorm = unicodedata.normalize('NFKD', unicode(ch))
              x = u"".join([c for c in chnorm if not unicodedata.combining(c)])
              if conv:
                  x = x.encode(encod)
              return x
          


          L'utilisation est la même que dans la fonction précédente, mais le traitement est plus élégant.

          Dernière difficulté possible: la console d'affichage a elle aussi un "encodage". Si l'affichage de chaines avec accents donne un mauvais résultat, c'est qu'une conversion d'encodage doit être fait pour l'affichage. Par exemple, pour afficher une chaine en 'latin1' dans la console cmd.exe de Windows, il faut la convertir en 'cp850':

          print chaine.decode('latin1').encode('cp850')
          


          Bon courage!
          • Partager sur Facebook
          • Partager sur Twitter
            7 octobre 2012 à 11:55:47

            ouaaah, merci beaucoup pour ces réponses précises ! J'étudie ça de plus près dans l'apres midi !

            edit :
            Ok, j'ai à priori opté pour la solution de tyrtamos, qui me semble familière, je crois avoir déjà vu ça auparavant.
            Malgré tout, je ne comprends pas certaines choses. En particulier le "u" qui se trouve avant la variable alpha1 et alpha2.

            Par exemple, j'aurai besoin d'appliquer cette fonction sur un truc que l'utilisateur rentre, ce qui veut dire que le query que j'utilise pour récupérer mon texte me renvoie une chaine de caractères. Je dois changer chaque chaine en un format unicode (donc avec le u devant), y appliquer la fonction, et le retransformer en string ?
            • Partager sur Facebook
            • Partager sur Twitter
              7 octobre 2012 à 16:14:56

              Citation : tyrtamos

              Dès qu'on veut traiter des chaines de caractères comportant des accents, on a un gros problème à traiter: celui de l'encodage. Si on s'y prend mal, cela risque même de planter un programme.
              [...]
              Je te propose 2 solutions (Python 2.7) pour retirer les accents sans changer la casse (les minuscules restent des minuscules, idem pour les majuscules).



              Bonjour,

              Je ne suis pas très familier avec python 2, mais si le PO est en python 3 la gestion de l'unicode est transparente (tout est unicode), et il y a des fonctions qui font déjà ce que tu propose. Ce qui donne au final un code beaucoup plus simple :

              def remove_accents(s):
                  alpha1 = "àÀâÂäÄåÅçÇéÉèÈêÊëËîÎïÏôÔöÖùÙûÛüÜÿŸ"
                  alpha2 = "aAaAaAaAcCeEeEeEeEiIiIoOoOuUuUuUyY"
                  return s.translate(str.maketrans(alpha1, alpha2))
              
              • Partager sur Facebook
              • Partager sur Twitter
              Anonyme
                7 octobre 2012 à 17:11:23

                Effectivement j'ai répondu avec Python 2.7, et je ne sais pas avec quel Python travaille fruity'. Ce serait bien qu'il nous le dise pour qu'on puisse lui donner de meilleures réponses.

                Sous Python 2.7, je n'utilise pas maketrans du module string parce qu'il ne supporte l'unicode. Pour être complet, il y a cependant une solution Python 2.7 avec translate si on réécrit maketrans:

                def sansaccent(ch, encod='utf-8'):
                    """Supprime les accents sans changer la casse (majuscules et minuscules)"""
                    alpha1 = u"àÀâÂäÄåÅçÇéÉèÈêÊëËîÎïÏôÔöÖùÙûÛüÜÿŸ"
                    alpha2 = u"aAaAaAaAcCeEeEeEeEiIiIoOoOuUuUuUyY"
                    conv = False
                    if not isinstance(ch, unicode):
                        ch = unicode(ch, encod,'replace')
                        conv = True
                    tableconv = {ord(a):b for a, b in zip(alpha1, alpha2)} # <== nouveau maketrans
                    x = chaine.translate(tableconv)
                    if conv:
                        x = x.encode(encod)
                    return x
                
                chaine = u"àÀâÂäÄåÅçÇéÉèÈêÊëËîÎïÏôÔöÖùÙûÛüÜ"
                print chaine
                àÀâÂäÄåÅçÇéÉèÈêÊëËîÎïÏôÔöÖùÙûÛüÜ
                print sansaccent(chaine)
                aAaAaAaAcCeEeEeEeEiIiIoOoOuUuUuU
                


                Si c'est Python 3.x, c'est plus simple puisque les chaines sont unicode par défaut. Cependant, La solution Python 3.x ne résout pas totalement le problème des encodages puisque les entrées/sorties ne sont, en général, pas en unicode. Sous Windows, la console est en 'cp850', et sous Ubuntu, elle est en 'utf-8'. Dans les 2 cas, l'encodage est donné par sys.stdin.encoding.

                @ yoch => pourrais-tu donner les formules de conversion d'encodage Python 3 dans les 2 sens: par exemple 'utf-8' ==> unicode et unicode ==> 'utf-8'?
                • Partager sur Facebook
                • Partager sur Twitter
                  8 octobre 2012 à 21:17:22

                  Citation : tyrtamos

                  @ yoch => pourrais-tu donner les formules de conversion d'encodage Python 3 dans les 2 sens: par exemple 'utf-8' ==> unicode et unicode ==> 'utf-8'?


                  Je ne comprends pas bien la question. UTF-8 est un des encodages possibles pour unicode, mais au niveau des str, on ne se pose pas la question de l'encodage puisque tout est unicode (et peu m'importe quel encodage interne, ce n'est pas le souci du programmeur). La seule question qui puisse se poser (en général) est pour ce qui concerne la conversion bytes -> str et assimilés (par exemple lorsque tu lis un fichier pour récupérer un str [mode text I/O], il faut spécifier un encodage).
                  • Partager sur Facebook
                  • Partager sur Twitter
                    8 octobre 2012 à 22:06:46

                    désolé de ne pas avoir précisé, je n'ai jamais le reflexe parce que je ne suis tout simplement pas vraiment au courant des différences entre python 2.7 et python 3 !
                    A vrai dire, je ne suis pas sûr non plus de ma version, et je ne sais pas comment la vérifier. Je travaille sur un soft 3d qui s'appelle maya (version 2013) et python est compris dans l'install. Je peux peut-être essayer de lancer un truc qui ne marche que dans python 3 pour voir quelle version j'ai (mais il me semble que c'est la 3).
                    En tout cas, merci encore pour les infos, j'ai réussi à faire ce que je voulais !
                    • Partager sur Facebook
                    • Partager sur Twitter
                      8 octobre 2012 à 22:22:04

                      Citation : fruity'

                      A vrai dire, je ne suis pas sûr non plus de ma version, et je ne sais pas comment la vérifier.



                      >>> import sys
                      >>> sys.version_info
                      sys.version_info(major=3, minor=2, micro=2, releaselevel='final', serial=0)
                      

                      • Partager sur Facebook
                      • Partager sur Twitter
                      Anonyme
                        9 octobre 2012 à 5:43:37

                        Bonjour,

                        @ yoch: merci pour la réponse (je ne travaille pas encore sous Python 3).

                        @ fruity': si print "toto" donne une erreur: tu as Python 3.x. Avec Python 3.x, print doit avoir des parenthèses: print("toto").
                        • Partager sur Facebook
                        • Partager sur Twitter
                          9 octobre 2012 à 18:06:35

                          ok, donc je suis visiblement en version 2.7, après vérification u_u'
                          je ne comprends pas pourquoi ne pas passer à la version 3 sachant que c'est gratuit de toute façon, m'enfin....
                          Merci encore pour votre aide !
                          • Partager sur Facebook
                          • Partager sur Twitter
                            9 octobre 2012 à 19:22:03

                            Citation : fruity'

                            je ne comprends pas pourquoi ne pas passer à la version 3 sachant que c'est gratuit de toute façon, m'enfin....


                            :lol:(à inscrire pour les perles du SdZ)
                            • Partager sur Facebook
                            • Partager sur Twitter
                              9 octobre 2012 à 19:22:52

                              ca le serait peut être moins si tu prenais 10 secondes pour m'expliquer =)
                              • Partager sur Facebook
                              • Partager sur Twitter
                                9 octobre 2012 à 19:36:02

                                Pour faire court : il existe des incompatibilités entre les 2 versions, qui peuvent décourager la transition de python 2 à python 3. Le reste, google te l'apprendra mieux que moi.
                                • Partager sur Facebook
                                • Partager sur Twitter
                                  9 octobre 2012 à 19:37:06

                                  ok, c'est tout ce que je voulais savoir, merci =)
                                  • Partager sur Facebook
                                  • Partager sur Twitter

                                  caractères spéciaux

                                  × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
                                  × Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
                                  • Editeur
                                  • Markdown