UnicodeDecodeError: кодек "utf8" не может декодировать байт 0x9c
У меня есть сервер сокетов, который должен принимать действительные символы UTF-8 от клиентов.
Проблема в том, что некоторые клиенты (в основном хакеры) отправляют через них все неправильные данные.
Я легко могу отличить подлинного клиента, но я записываю в файлы все отправленные данные, чтобы потом проанализировать их.
Иногда я получаю таких персонажей œ
это вызывает UnicodeDecodeError
ошибка.
Мне нужно иметь возможность сделать строку UTF-8 с или без этих символов.
Обновить:
Для моего конкретного случая служба сокетов была MTA, и поэтому я ожидаю только получения команд ASCII, таких как:
EHLO example.com
MAIL FROM: <john.doe@example.com>
...
Я записывал все это в формате JSON.
Тогда некоторые люди без добрых намерений решили продать все виды мусора.
Вот почему для моего конкретного случая вполне нормально удалить символы, не входящие в ASCII.
14 ответов
http://docs.python.org/howto/unicode.html
str = unicode(str, errors='replace')
или же
str = unicode(str, errors='ignore')
Примечание: это решение удалит (проигнорирует) символы, возвращающие строку без них. Используйте это только если вам нужно раздеть их, а не конвертировать.
В качестве альтернативы используйте метод open из codecs
Модуль для чтения в файле:
import codecs
with codecs.open(file_name, "r",encoding='utf-8', errors='ignore') as fdata:
Смена движка с C на Python сделала мой трюк.
Двигатель C:
pd.read_csv(gdp_path, sep='\t', engine='c')
Кодек utf-8 не может декодировать байт 0x92 в позиции 18: недопустимый начальный байт
Двигатель Python:
pd.read_csv(gdp_path, sep='\t', engine='python')
Нет ошибок для меня.
Этот тип проблем возник у меня сейчас, когда я перешел на Python 3. Я понятия не имел, что Python 2 просто обрабатывает любые проблемы с кодировкой файлов.
Я нашел это хорошее объяснение различий и того, как найти решение после того, как ничего из вышеперечисленного не помогло мне.
http://python-notes.curiousefficiency.org/en/latest/python3/text_file_processing.html
Короче говоря, чтобы заставить Python 3 вести себя как можно ближе к использованию Python 2:
with open(filename, encoding="latin-1") as datafile:
# work on datafile here
Тем не менее, прочитайте статью, там не один размер подходит для всех решений.
Первый , используя get_encoding_type, чтобы получить тип файла кодирования:
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']
во-вторых, открывая файлы с типом:
open(current_file, 'r', encoding = get_encoding_type, errors='ignore')
>>> '\x9c'.decode('cp1252')
u'\u0153'
>>> print '\x9c'.decode('cp1252')
œ
У меня была такая же проблема с UnicodeDecodeError
и я решил это с этой строкой. Не знаю, если это лучший способ, но это сработало для меня.
str = str.decode('unicode_escape').encode('utf-8')
Я решил эту проблему, просто добавив
df = pd.read_csv(fileName,encoding='latin1')
Я решил эту проблему с помощью этого кода
df = pd.read_csv(gdp_path, engine='python')
На всякий случай у кого-то такая же проблема. Я использую vim с YouCompleteMe, мне не удалось запустить ycmd с этим сообщением об ошибке, что я сделал: export LC_CTYPE="en_US.UTF-8"
проблема исчезла
Что вы можете сделать, если вам нужно внести изменения в файл, но вы не знаете кодировку файла? Если вы знаете, что кодировка совместима с ASCII, и хотите проверять или изменять только части ASCII, вы можете открыть файл с помощью обработчика ошибок surrogateescape:
with open(fname, 'r', encoding="ascii", errors="surrogateescape") as f:
data = f.read()
Если, как вы говорите, вы просто хотите разрешить чистый 7-битный ASCII, просто отбросьте все байты, которые не являются таковыми. В любом случае нет простого способа угадать, что удаленный конец намеревался их представлять, без явно указанной кодировки.
while bytes := socket.read_line_bytes():
try:
string = bytes.decode('us-ascii')
except UnicodeDecodeError as exc:
logger.warning('[%s] - rejected non-ASCII input %s' % (client, bytes.decode('us-ascii', errors='backslashreplace'))
socket.write(b'421 communication error - non-ASCII content rejected\r\n')
continue
...
У меня была такая же ошибка.
Для меня Python жаловался на байт «0x87». Я посмотрел его на https://bytetool.web.app/en/ascii/code/0x87/ , где мне сказали, что этот байт принадлежит кодеку Windows-1252.
Затем я добавил эту строку только в начало моего файла Python:
#-*- encoding: Windows-1252 -*-"
И все ошибки исчезли. Прежде чем я добавил эту строку, я попытался Pandas импортировать файл следующим образом:
Df = pd.read_csv(data, sep=",", engine='python', header=0, encoding='Windows-1252')
но это вернуло мне ошибку. Поэтому я изменил его обратно на это:
Df = pd.read_csv(data, sep=",", engine='python', header=0)
Аналогичная ошибка, например
UnicodeDecodeError: 'utf-8' codec can't decode byte 0xa0 in position 22: invalid start byte
также отображается, если кто-то пытается открыть файл Excel с помощьюread_csv()
в пандах. С использованиемpd.read_excel()
вместо этого решает ошибку.
Пример, демонстрирующий это (имя файла — data_dictionary, поскольку словари данных чаще всего представляют собой файлы Excel, а сами наборы данных — файлы CSV).
import pandas as pd
# some sample data
df = pd.DataFrame({'A': [1, 2, 3], 'B': ['a', 'b', 'c']})
df.to_excel('data_dictionary.xlsx', index=False)
df = pd.read_csv("data_dictionary.xlsx") # <----- error
df = pd.read_excel("data_dictionary.xlsx") # <----- OK
- django-storage неявно поддерживается чтение байтового файла в текстовом режиме до django-storage == 1.8
- Удалена поддержка в https://github.com/jschneier/django-storages/pull/657 .
- Необходимо указать бинарный режим для чтения байтовых файлов.