web-dev-qa-db-fra.com

Passage à Python 3 provoquant UnicodeDecodeError

Je viens d'ajouter un interpréteur Python3 à Sublime et le code suivant a cessé de fonctionner:

for directory in directoryList:
    fileList = os.listdir(directory)
    for filename in fileList:
        filename = os.path.join(directory, filename)
        currentFile = open(filename, 'rt')
        for line in currentFile:               ##Here comes the exception.
            currentLine = line.split(' ')
            for Word in currentLine:
                if Word.lower() not in bigBagOfWords:
                    bigBagOfWords.append(Word.lower())
        currentFile.close()

Je reçois une exception suivante:

  File "/Users/Kuba/Desktop/DictionaryCreator.py", line 11, in <module>
    for line in currentFile:
  File "/Library/Frameworks/Python.framework/Versions/3.4/lib/python3.4/encodings/ascii.py", line 26, in decode
    return codecs.ascii_decode(input, self.errors)[0]
UnicodeDecodeError: 'ascii' codec can't decode byte 0xcc in position 305: ordinal not in range(128)

J'ai trouvé cela plutôt étrange, car, autant que je sache, Python3 est supposé prendre en charge utf-8 partout. De plus, le même code exact fonctionne sans problèmes sur Python2.7. J'ai lu des articles sur l'ajout de la variable d'environnement PYTHONIOENCODING, mais je l'ai essayé - en vain (cependant, il semble que ce ne soit pas facile d'ajouter une variable d'environnement dans OS X Mavericks, alors j'ai peut-être mal fait d'ajouter cette variable? modidifié /etc/launchd.conf)

21
3yakuya

Python 3 décode les fichiers texte lors de la lecture. Le codage par défaut provient de locale.getpreferredencoding(False) , qui renvoie évidemment 'ASCII' à votre configuration. Voir la documentation de la fonction open() :

En mode texte, si encoding n'est pas spécifié, l'encodage utilisé dépend de la plate-forme: locale.getpreferredencoding(False) est appelé pour obtenir l'encodage des paramètres régionaux en cours.

Au lieu de vous fier à un paramètre système, vous devez ouvrir vos fichiers texte à l'aide d'un codec explicite:

currentFile = open(filename, 'rt', encoding='latin1')

où vous définissez le paramètre encoding pour correspondre au fichier que vous lisez.

Python 3 prend en charge UTF-8 comme valeur par défaut pour code source.

La même chose s'applique à l'écriture dans un fichier texte inscriptible; les données écrites seront codées et si vous utilisez le codage système, vous êtes susceptible d'obtenir des exceptions UnicodeEncodingError à moins que vous ne définissiez explicitement un codec approprié.

Vous voudrez peut-être lire sur Python 3 et Unicode dans le Unicode HOWTO , qui explique le codage du code source ainsi que la lecture et l’écriture de données Unicode.

54
Martijn Pieters

"pour autant que je sache, Python3 est supposé prendre en charge utf-8 partout ..." C'est faux. J'ai python 3.6 et mon encodage par défaut n'est pas utf-8. Pour le changer en utf-8 dans mon code, j'utilise:

import locale
def getpreferredencoding(do_setlocale = True):
   return "utf-8"
locale.getpreferredencoding = getpreferredencoding

comme expliqué dans Modification du "codage par défaut des paramètres régionaux" dans Python 3 sous Windows

0
farid khafizov