web-dev-qa-db-fra.com

UnicodeDecodeError: le codec 'utf8' ne peut pas décoder l'octet 0x9c

J'ai un serveur de socket qui est supposé recevoir les caractères valides UTF-8 des clients.

Le problème est que certains clients (principalement les pirates informatiques) envoient tout le mauvais type de données par dessus.

Je peux facilement distinguer le client authentique, mais je suis en train de consigner dans un fichier toutes les données envoyées pour pouvoir les analyser ultérieurement.

Parfois, je reçois des caractères tels que œ qui provoquent l'erreur UnicodeDecodeError.

Je dois être capable de faire la chaîne UTF-8 avec ou sans ces caractères.


Mettre à jour:

Dans mon cas particulier, le service de socket était un MTA et je m'attends donc uniquement à recevoir des commandes ASCII telles que:

EHLO example.com
MAIL FROM: <[email protected]>
...

Je me connectais tout cela en JSON.

Puis des gens sans bonnes intentions ont décidé de vendre toutes sortes de bric-à-brac.

C'est pourquoi, dans mon cas spécifique, il est parfaitement correct de supprimer les caractères non ASCII.

203
transilvlad

http://docs.python.org/howto/unicode.html#the-unicode-type

str = unicode(str, errors='replace')

ou

str = unicode(str, errors='ignore')

Remarque: _ ​​Ceci supprimera (ignorera) les caractères en question renvoyant la chaîne sans eux.

Pour moi, c'est le cas idéal, car je l'utilise comme protection contre les entrées non-ASCII, ce que mon application ne permet pas.

Alternativement: Utilisez la méthode open du module codecs pour lire dans le fichier:

import codecs
with codecs.open(file_name, "r",encoding='utf-8', errors='ignore') as fdata:
272
transilvlad

Ce type de problème me revient maintenant que je suis passé à Python 3. Je ne savais pas que Python 2 était simplement propulsé par Steam pour résoudre les problèmes d'encodage de fichier. 

J'ai trouvé cette explication intéressante des différences et de la façon de trouver une solution après que rien de ce qui précède n'ait fonctionné pour moi. 

http://python-notes.curiousefficiency.org/en/latest/python3/text_file_processing.html

En bref, pour que Python 3 se comporte de manière aussi semblable que possible à Python 2, utilisez:

with open(filename, encoding="latin-1") as datafile:
    # work on datafile here

Cependant, lisez l'article, il n'y a pas de solution unique. 

45
James McCormac

Changer le moteur de C à Python a été le bon choix pour moi.

Le moteur est C:

pd.read_csv(gdp_path, sep='\t', engine='c')

Le codec 'utf-8' ne peut pas décoder l'octet 0x92 en position 18: octet de début non valide

Le moteur est Python:

pd.read_csv(gdp_path, sep='\t', engine='python')

Aucune erreur pour moi.

37
Doğuş Bıçak
>>> '\x9c'.decode('cp1252')
u'\u0153'
>>> print '\x9c'.decode('cp1252')
œ
26

J'ai eu le même problème avec UnicodeDecodeError et je l'ai résolu avec cette ligne . Je ne sais pas si c'est le meilleur moyen mais ça a fonctionné pour moi.

str = str.decode('unicode_escape').encode('utf-8')
16
maiky_forrester

Juste au cas où quelqu'un aurait le même problème. J'utilise vim avec YouCompleteMe , échec du démarrage de ycmd avec ce message d'erreur. Ce que j'ai fait est: export LC_CTYPE="en_US.UTF-8", le problème a disparu.

2
hylepo

Que pouvez-vous faire si vous devez modifier un fichier sans connaître le codage du fichier? Si vous savez que le codage est compatible ASCII et souhaitez uniquement examiner ou modifier les parties ASCII, vous pouvez ouvrir le fichier à l'aide du gestionnaire d'erreurs surrogateescape:

with open(fname, 'r', encoding="ascii", errors="surrogateescape") as f:
    data = f.read()

le premier, Utilisation de get_encoding_type pour obtenir le type de fichier encodé:

import os    
from chardet import detect

# get file encoding type
def get_encoding_type(file):
    with open(file, 'rb') as f:
        rawdata = f.read()
    return detect(rawdata)['encoding']

la seconde, ouvrant les fichiers avec le type:

open(current_file, 'r', encoding = get_encoding_type, errors='ignore')
0
Ivan Lee