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 .
  • Необходимо указать бинарный режим для чтения байтовых файлов.
Другие вопросы по тегам