Функции encode() и decode() в Python
Методы encode и decode Python используются для кодирования и декодирования входной строки с использованием заданной кодировки. Давайте подробно рассмотрим эти две функции.
encode заданной строки
Мы используем метод encode() для входной строки, который есть у каждого строкового объекта.
Это кодирует input_string с использованием encoding , где errors определяют поведение, которому надо следовать, если по какой-либо случайности кодирование строки не выполняется.
encode() приведет к последовательности bytes .
Как и ожидалось, в результате получается объект :
Тип кодирования, которому надо следовать, отображается параметром encoding . Существуют различные типы схем кодирования символов, из которых в Python по умолчанию используется схема UTF-8.
Рассмотрим параметр encoding на примере.
Как вы можете заметить, мы закодировали входную строку в формате UTF-8. Хотя особой разницы нет, вы можете заметить, что строка имеет префикс b . Это означает, что строка преобразуется в поток байтов.
На самом деле это представляется только как исходная строка для удобства чтения с префиксом b , чтобы обозначить, что это не строка, а последовательность байтов.
Обработка ошибок
Существуют различные типы errors , некоторые из которых указаны ниже:
Тип ошибки | Поведение |
strict | Поведение по умолчанию, которое вызывает UnicodeDecodeError при сбое. |
ignore | Игнорирует некодируемый Unicode из результата. |
replace | Заменяет все некодируемые символы Юникода вопросительным знаком (?) |
backslashreplace | Вставляет escape-последовательность обратной косой черты (\ uNNNN) вместо некодируемых символов Юникода. |
Давайте посмотрим на приведенные выше концепции на простом примере. Мы рассмотрим входную строку, в которой не все символы кодируются (например, ö ),
Декодирование потока байтов
Подобно кодированию строки, мы можем декодировать поток байтов в строковый объект, используя функцию decode() .
Поскольку encode() преобразует строку в байты, decode() просто делает обратное.
Это показывает, что decode() преобразует байты в строку Python.
Подобно параметрам encode() , параметр decoding определяет тип кодирования, из которого декодируется последовательность байтов. Параметр errors обозначает поведение в случае сбоя декодирования, который имеет те же значения, что и у encode() .
Важность кодировки
Поскольку кодирование и декодирование входной строки зависит от формата, мы должны быть осторожны при этих операциях. Если мы используем неправильный формат, это приведет к неправильному выводу и может вызвать ошибки.
Первое декодирование неверно, так как оно пытается декодировать входную строку, которая закодирована в формате UTF-8. Второй правильный, поскольку форматы кодирования и декодирования совпадают.
VladSem / check_incoding.py
#!/usr/bin/python |
# -*- coding: utf-8 -*- |
import chardet |
import Tkinter |
from Tkinter import Label |
from Tkinter import Tk |
from Tkinter import X |
from tkFileDialog import askopenfilename |
import os |
def open_file (): |
try : |
filename = askopenfilename () |
f = open ( filename , ‘r’ ). read () |
except UnicodeDecodeError : |
print «can’t open this file» |
else : |
try : |
encoding = chardet . detect ( f ) |
print encoding |
except UnicodeDecodeError : |
print ( ‘can \’ t detect encoding’ ) |
else : |
if encoding [ ‘encoding’ ] == ‘ascii’ : |
print ‘Encoding is: ascii’ |
elif encoding [ ‘encoding’ ] == ‘windows-1251’ : |
res . configure ( text = «Encoding is: windows-1251» , fg = «blue» ) |
elif encoding [ ‘encoding’ ] == ‘utf-8’ : |
res . configure ( text = «Encoding is: utf-8» , fg = «blue» ) |
elif encoding [ ‘encoding’ ] == ‘None’ : |
res . configure ( text = «Encoding is: None» , fg = «blue» ) |
else : |
res . configure ( text = ‘Encoding can \’ t be detected’ , fg = «blue» ) |
print ‘Encoding can \’ t be detected’ |
def convert_from_windows_1251 (): |
filename = askopenfilename () |
try : |
f = open ( filename , ‘r’ ). read () |
except UnicodeDecodeError : |
print «it was not a windows-1251 unicode» |
else : |
try : |
unicode_text = f . decode ( ‘cp1251’ ) |
except UnicodeDecodeError : |
print ( ‘unicode error, trying different encoding’ ) |
else : |
abs_path = os . path . join ( os . path . dirname ( __file__ ), ‘output_from_cp1251_to_utf8.txt’ ) |
text_in_1251 = unicode_text . encode ( ‘utf-8’ ) |
f = open ( abs_path , ‘w’ ) |
f . write ( text_in_1251 ) |
def convert_from_utf8_to_windows_1251 (): |
filename = askopenfilename () |
try : |
f = open ( filename , ‘r’ ). read () |
except UnicodeDecodeError : |
print «it was not a utf-8 unicode» |
else : |
try : |
unicode_text = f . decode ( ‘utf-8’ ) |
except UnicodeDecodeError : |
print ( ‘unicode error, trying different encoding’ ) |
else : |
abs_path = os . path . join ( os . path . dirname ( __file__ ), ‘output_from_utf8_to_cp1251.txt’ ) |
text_in_1251 = unicode_text . encode ( ‘cp1251’ ) |
f = open ( abs_path , ‘w’ ) |
f . write ( text_in_1251 ) |
root = Tk () |
root . title ( ‘UTF-8 Converter’ ) |
root . geometry ( ‘250×250+500+300’ ) |
root . config ( background = «#FFFFFF» ) |
button = Tkinter . Button ( root , text = «Check encoding» , width = 25 , bg = «#FFFFFF» , command = open_file ) |
button . pack ( fill = X , padx = 10 , pady = 20 ) |
res = Label ( root , bg = «#FFFFFF» ) |
res . pack () |
button1 = Tkinter . Button ( root , text = «Convert from windows-1251 to utf-8» , width = 25 , bg = «#FFFFFF» , |
command = convert_from_windows_1251 ) |
button1 . pack ( fill = X , padx = 10 , pady = 15 ) |
button1 = Tkinter . Button ( root , text = «Convert from utf-8 to windows-1251» , width = 25 , bg = «#FFFFFF» , |
command = convert_from_utf8_to_windows_1251 ) |
button1 . pack ( fill = X , padx = 10 , pady = 15 ) |
exit_button = Tkinter . Button ( root , text = ‘Quit’ , command = root . destroy , bg = «#FFFFFF» ) |
exit_button . pack ( side = ‘bottom’ ) |
root . mainloop () |
You can’t perform that action at this time.
You signed in with another tab or window. Reload to refresh your session. You signed out in another tab or window. Reload to refresh your session.
How to convert a string from CP-1251 to UTF-8?
I’m using mutagen to convert ID3 tags data from CP-1251/CP-1252 to UTF-8. In Linux there is no problem. But on Windows, calling SetValue() on a wx.TextCtrl produces the error:
UnicodeDecodeError: ‘ascii’ codec can’t decode byte 0xc3 in position 0: ordinal not in range(128)
The original string (assumed to be CP-1251 encoded) that I’m pulling from mutagen is:
I’ve tried converting this to UTF-8:
. and even changing the default encoding from ASCII to UTF-8:
. But I get the same error.
6 Answers 6
If you know for sure that you have cp1251 in your input, you can do
Your string d is a Unicode string, not a UTF-8-encoded string! So you can’t decode() it, you must encode() it to UTF-8 or whatever encoding you need.
(which is something you’d do at the very end of all processing when you need to save it as a UTF-8 encoded file, for example).
If your input is in a different encoding, it’s the other way around:
If d is a correct Unicode string, then d.encode(‘utf-8’) yields an encoded UTF-8 bytestring. Don’t test it by printing, though, it might be that it just doesn’t display properly because of the codepage shenanigans.
I’d rather add a comment to Александр Степаненко answer but my reputation doesn’t yet allow it. I had similar problem of converting MP3 tags from CP-1251 to UTF-8 and the solution of encode/decode/encode worked for me. Except for I had to replace first encoding with «latin-1», which essentially converts Unicode string into byte sequence without real encoding:
and for saving back using for example mutagen it doesn’t need to be encoded:
I provided some relevant info on encoding/decoding text in this response: https://stackoverflow.com/a/34662963/2957811
To add to that here, it’s important to think of text in one of two possible states: ‘encoded’ and ‘decoded’
‘decoded’ means it is in an internal representation by your interpreter/libraries that can be used for character manipulation (e.g. searches, case conversion, substring slicing, character counts, . ) or display (looking up a code point in a font and drawing the glyph), but cannot be passed in or out of the running process.
‘encoded’ means it is a byte stream that can be passed around as can any other data, but is not useful for manipulation or display.
If you’ve worked with serialized objects before, consider ‘decoded’ to be the useful object in memory and ‘encoded’ to be the serialized version.
‘\xc1\xe5\xeb\xe0\xff \xff\xe1\xeb\xfb\xed\xff \xe3\xf0\xee\xec\xf3’ is your encoded (or serialized) version, presumably encoded with cp1251. This encoding needs to be right because that’s the ‘language’ used to serialize the characters and is needed to recreate the characters in memory.