Как узнать кодировку строки python
Перейти к содержимому

Как узнать кодировку строки python

  • автор:

Как определить кодировку строки (в string, а не bytes) в Python?

Т.е. нужна либо другая функция для string, либо string нужно превратить в bytes. Подскажите пожалуйста, как это сделать?

Отслеживать
задан 23 окт 2017 в 12:20
Ruslan Sagitov Ruslan Sagitov
11 1 1 золотой знак 1 1 серебряный знак 5 5 бронзовых знаков

1 ответ 1

Сортировка: Сброс на вариант по умолчанию

Ошибка указывает, что у вас Питон 3, где str тип, используется для текста — каждая строка (str) это последовательность символов (Unicode codepoints).

Сами символы никакой кодировки не имеют (как внутри интерпретатора строки представлены не имеет значения, до тех пор пока абстракция не нарушена).

Любая кодировка, которая может представить все символы в строке, может быть использована:

>>> "мир".encode('utf-8') b'\xd0\xbc\xd0\xb8\xd1\x80' >>> "мир".encode('cp1251') b'\xec\xe8\xf0' >>> "мир".encode('cp866') b'\xac\xa8\xe0' >>> "мир".encode('koi8-r') b'\xcd\xc9\xd2' 

Сама строка никакой кодировки не имеет. Ещё примеры: Как работать с путями c русскими символами?

Вопрос, который можно для строки задать: на каком языке вероятно текст написан? Или более узкий (определённый) вопрос: принадлежат ли все букву заданному диапазону в Unicode.

  • Python: How to determine the language?
  • How to match Cyrillic characters with a regular expression

Как узнать кодировку строки python

На этом шаге мы рассмотрим методы решения указанной задачи .

Документы в Интернете могут быть представлены в различных кодировках. Чтобы документ был правильно обработан, необходимо знать его кодировку. Определить кодировку можно по заголовку Content-Type в заголовках ответа Web -сервера:

Content-Type: text/html; charset=utf-8

Кодировку Web -страницы можно также определить по значению параметра content тега , расположенного в разделе HEAD :

Однако часто встречается ситуация, когда кодировка в ответе сервера не совпадает с кодировкой, указанной в теге , или же таковая вообще не указана. Определить кодировку документа в этом случае позволяет библиотека chardet . Установить ее можно из репозитория PyPI способом, описанным на 228 шаге. Открываем командную строку и набираем в ней команду:

c:\python34\scripts\pip install chardet

Через некоторое время библиотека будет установлена.

Для проверки установки запускаем редактор IDLE и в окне Python Shell выполняем следующий код:

>>> import chardet >>> chardet.__version__ '3.0.4' 

Определить кодировку строки позволяет функция detect (< Последовательность байтов >) из модуля chardet . В качестве результата она возвращает словарь с тремя элементами. Ключ encoding содержит название кодировки, ключ language — название языка, а ключ confidence — коэффициент точности определения в виде вещественного числа от 0 до 1. Пример определения кодировки приведен ниже.

>>> import chardet >>> chardet.detect(bytes(«Строка», «cp1251»)) >>> chardet.detect(bytes(«Строка», «utf-8»))

Если файл имеет большой размер, то вместо считывания его целиком в строку и использования функции detect() можно воспользоваться классом UniversalDetector . В этом случае можно читать файл построчно и передавать текущую строку методу feed() . Если определение кодировки прошло успешно, атрибут done будет иметь значение True . Это условие можно использовать для выхода из цикла. После окончания проверки следует вызвать метод close() . Получить результат определения кодировки позволяет атрибут result . Очистить результат и подготовить объект к дальнейшему определению кодировки можно с помощью метода reset() . Пример использования класса UniversalDetector приведен ниже.

from chardet.universaldetector import UniversalDetector ud = UniversalDetector() # Создаем объект for line in open("file.txt", "rb"): ud.feed(line) # Передаем текущую строку if ud.done: break # Прерываем цикл, если done == True ud.close() # Закрываем объект print(ud.result) # Выводим результат 

Архив с файлом можно взять здесь.

Результат работы приложения:

Как показали тесты, при использовании кодировки Windows-1251 файл просматривается полностью, и определение кодировки файла, содержащего 6500 строк, занимает почти секунду. Если сменить кодировку файла на UTF-8 без ВОМ , то время определения увеличивается до 5 секунд. Использовать класс UniversalDetector или нет — решать вам.

Замечание . Полное описание библиотеки chardet можно найти по адресу http://chardet.readthedocs.org/en/latest/ .

Со следующего шага мы начнем рассматривать сжатие данных .

Как определить кодировку строки и преобразовать в utf8?

Через imap подключаюсь к серверу и получаю список сообщений. Проблема в кодировке тела письма — в гугле оно одно, в яндексе другое. Хочу чтобы система автоматом определяла кодировку и преобразовывала его в utf8

import cchardet def convert_encoding(data, new_coding = 'UTF-8'): encoding = cchardet.detect(data)['encoding'] if new_coding.upper() != encoding.upper(): data = data.decode(encoding, data).encode(new_coding) return data def get_mails(login, password): print("Connecting to <>. ".format(server)) imap = imaplib.IMAP4_SSL(server) print("Connected! Logging in as <>. ".format(login)); imap.login(login, password) print("Logged in! Listing messages. "); status, select_data = imap.select('INBOX') nmessages = select_data[0].decode('utf-8') status, search_data = imap.search(None, 'ALL') for msg_id in search_data[0].split(): status, msg_data = imap.fetch(msg_id, '(RFC822)') msg_raw = msg_data[0][1].decode("utf8") mail = mailparser.parse_from_string(msg_raw) telo = convert_encoding(mail.body.encode()) # Вот тут траблы

Для примера — mail.body содержит следующий текст

'
\\u041f\\u0440\\u043e\\u0432\\u0435\\u0440\\u043a\\u0430 \\u0441
'

Выдаёт ошибку
TypeError: decode() argument 2 must be str, not bytes

  • Вопрос задан более трёх лет назад
  • 1672 просмотра

5 комментариев

Средний 5 комментариев

Кодировки в python

В python есть 2 объекта работающими с текстом: unicode и str, объект unicode хранит символы в формате (кодировке) unicode, объект str является набором байт/символов в которых python хранит остальные кодировки (utf8, cp1251, cp866, koi8-r и др).

Кодировку unicode можно считать рабочей кодировкой питона т.к. она предназначена для её использования в самом скрипте — для разных операций над строками.
Внешняя кодировка (объект str) предназначена для хранения и передачи текстовой информации вне скрипта, например для сохранения в файл или передачи по сети. Поэтому в данной статье я её назвал внешней. Самой используемой кодировкой в мире является utf8 и число приложений переходящих на эту кодировку растет каждый день, таким образом превращаясь в «стандарт». Эта кодировка хороша тем что для хранения текста она занимает оптимальное кол-во памяти и с помощью её можно закодировать почти все языки мира ( в отличие от cp1251 и подобных однобайтовых кодировок). Поэтому рекомендуется везде использовать utf8, и при написании скриптов.

Использование

Скрипт питона, в самом начале скрипта указываем кодировку файла и сохраняем в ней файл

# coding: utf8 
# -*- coding: utf-8 -*- 

для того что-бы интерпретатор python понял в какой кодировке файл

Строки в скрипте
Строки в скрипте хранятся байтами, от кавычки до кавычки:

print 'Привет' 

= 6 байт при cp1251
= 12 байт при utf8

Если перед строкой добавить символ u, то при запуске скрипта, эта байтовая строка будет декодирована в unicode из кодировки указанной в начале:

# coding:utf8 print u'Привет' 

и если кодировка содержимого в файле отличается от указанной, то в строке могут быть «битые символы»

Загрузка и сохранение файла

# coding: utf8 # Загружаем файл с кодировкай utf8 text = open('file.txt','r').read() # Декодируем из utf8 в unicode - из внешней в рабочую text = text.decode('utf8') # Работаем с текстом text += text # Кодируем тест из unicode в utf8 - из рабочей во внешнюю text = text.encode('utf8') # Сохраняем в файл с кодировкий utf8 open('file.txt','w').write(text) 

Текст в скрипте

# coding: utf8 a = 'Текст в utf8' b = u'Текст в unicode' # Эквивалентно: b = 'Текст в unicode'.decode('utf8') # т.к. сам скрипт хранится в utf8 print 'a =',type(a),a # декодируем из utf-8 в unicode и далее unicode в cp866 (кодировка консоли winXP ru) print 'a2 =',type(a),a.decode('utf8').encode('cp866') print 'b =',type(b),b 

Процедуре print текст желательно передавать в рабочей кодировке либо кодировать в кодировку ОС.
Результат скрипта при запуске из консоли windows XP:

a = type 'str'> ╨в╨╡╨║╤Б╤В ╨▓ utf8 a2 = type 'str'> Текст в utf8 b = type 'unicode'> Текст в unicode 

В последней строке print преобразовал unicode в cp866 автоматический, см. следующий пункт

Авто-преобразование кодировки
В некоторых случаях для упрощения разработки python делает преобразование кодировки, пример с методом print можно посмотреть в предыдущем пункте.
В примере ниже, python сам переводит utf8 в unicode — приводит к одной кодировке для того что-бы сложить строки.

# coding: utf8 # Устанавливаем стандартную внешнюю кодировку = utf8 import sys reload(sys) sys.setdefaultencoding('utf8') a = 'Текст в utf8' b = u'Текст в unicode' c = a + b print 'a =',type(a),a print 'b =',type(b),b print 'c =',type(c),c 
a = type 'str'> Текст в utf8 b = type 'unicode'> Текст в unicode c = type 'unicode'> Текст в utf8Текст в unicode 

Как видим результирующая строка «c» в unicode. Если бы кодировки строк совпадали то авто-перекодирования не произошло бы и результирующая строка содержала кодировку слагаемых строк.
Авто-перекодирование обычно срабатывает когда происходит взаимодействие разных кодировок.

Пример авто-преобразования кодировок в сравнении

# coding: utf8 # Устанавливаем стандартную внешнюю кодировку = utf8 import sys reload(sys) sys.setdefaultencoding('utf8') print '1. utf8 and unicode', 'true' if u'Слово'.encode('utf8') == u'Слово' else 'false' print '2. utf8 and cp1251', 'true' if u'Слово'.encode('utf8') == u'Слово'.encode('cp1251') else 'false' print '3. cp1251 and unicode', 'true' if u'Слово'.encode('cp1251') == u'Слово' else 'false' 
1. utf8 and unicode true 2. utf8 and cp1251 false script.py:10: UnicodeWarning: Unicode equal comparison failed to convert both arguments to Unicode - interpreting them as being unequal print '3. cp1251 and unicode', 'true' if u'Слово'.encode('cp1251') == u'Слово' else 'false' 3. cp1251 and unicode false 

В сравнении 1, кодировка utf8 преобразовалась в unicode и сравнение произошло корректно.
В сравнении 2, сравниваются кодировки одного вида — обе внешние, т.к. кодированы они в разных кодировках условие выдало что они не равны.
В сравнении 3, выпало предупреждение из за того что выполняется сравнение кодировок разного вида — рабочая и внешняя, а авто-декодирование не произошло т.к. стандартная внешняя кодировка = utf8, и декодировать строку в кодировке cp1251 методом utf8 питон не смог.

# coding: utf8 d = ['Тест','списка'] print '1',d print '2',d.__repr__() print '3',','.join(d) 
1 ['\xd0\xa2\xd0\xb5\xd1\x81\xd1\x82', '\xd1\x81\xd0\xbf\xd0\xb8\xd1\x81\xd0\xba\xd0\xb0'] 2 ['\xd0\xa2\xd0\xb5\xd1\x81\xd1\x82', '\xd1\x81\xd0\xbf\xd0\xb8\xd1\x81\xd0\xba\xd0\xb0'] 3 Тест,списка 

При выводе списка, происходит вызов [<repr>]() который возвращает внутреннее представление этого спиcка — print 1 и 2 являются аналогичными. Для корректного вывода списка, его нужно преобразовать в строку — print 3.

Установка внешней кодировки при запуске

PYTHONIOENCODING=utf8 python 1.py 

статья будет дополняться.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *