Python decode windows 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: '

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.

'xc1xe5xebxe0xff xffxe1xebxfbxedxff xe3xf0xeexecxf3' 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.

You need to decode this from it’s current encoding (cp1251) into python unicode characters, then re-encode it as a utf8 byte stream. The answerer that suggested d.decode('cp1251').encode('utf8') had this right, I am just hoping to help explain why that should work.

February 6 2011, 10:41

Вечно путаюсь в этих кодировках, поэтому решил сделать себе памятку. Покажу на примере.

Итак, кодировка исходного кода задается в первой-второй строке:

#-*-coding: UTF-8 -*-

Далее, допустим мы парсим какой-то сайт в windows-1251:

raw_data = urllib.urlopen(«bla bla bla»).read()

Мы получили данные, и сейчас они находятся в кодировке 1251, а исходник в utf-8, и нам нужно воспользоватся регулярками с кириллицей чтобы что-нибудь найти, выражение:

data = re.findall(r’Данные.*?<.*?>(.*?)</>’, raw_data)

выдаст нам пустой массив, потомому что данные в 1251 а регулярка в utf-8. В питоне есть несколько функций для перекодирования:

decode(‘WINDOWS-1251’) — декодирует строку из кодировки 1251 в ЮНИКОД(ЮНИКОД != UTF-8)
encode(‘UTF-8’) — кодирует строку из юникода в UTF-8.

Что касается Юникод vs UTF-8, то:
UNICODE: u’u041cu0430u043cu0430 u043cu044bu043bu0430 u0440u0430u043cu0443′
UTF-8: ‘xd0x9cxd0xb0xd0xbcxd0xb0 xd0xbcxd1x8bxd0xbbxd0xb0 xd1x80xd0xb0xd0xbcxd1x83’
нормальный вид: ‘Мама мыла раму’

Итак, чтобы у нас не было проблем с кодировками, нам достаточно сделать вот так:

raw_data = urllib.urlopen(«bla bla bla»).read().decode(‘WINDOWS-1251’).encode(‘UTF-8’)

И теперь наша запарсеная страница в той же кодировке что и исходник программы, и можно смело использовать кириллицу в регулярках, или в других ваших решениях. Конечно это не единственное решение, но в моем случае самое простое и удобное.

Я, и пожалуй это не удивительно, люблю аниме, как и многие в современном мире. Единственное — терпеть не могу русскую озвучку и предпочитаю смотреть с субтитрами. Но…большинство релизеров сидят на windows и совершенно не думаю о том, что существуют других ОС, для которых кодировка windows-1251 не то что не является родной, но и вообще корректно не отображается. Начав не так давно изучать python, стал думать о различных, полезных для «дома» скриптах, а прочитав на днях статью на хабре Приводим русские тексты на Mac OS X в одну кодировку Python-скриптом, как то оно меня подтолкнуло к написанию простенького скрипта, который бы этим и занимался. О нём и расскажу.

Сам скрипт достаточно простенький и небольшой, вот листинг:

#!/usr/bin/python
# -*- coding: utf-8 -*-

import os
import sys
import chardet

def converter(filePath):
	if any([filePath.endswith(extension) for extension in '.srt,.ass,.txt'.split(',')]):
		with open(filePath, "rb") as F:
			text = F.read()
			enc = chardet.detect(text).get("encoding")
			if enc and enc.lower() != "utf-8":
				try:
					text = text.decode(enc)
					text = text.encode("utf-8")
					with open(filePath, "wb") as f:
						f.write(text)
						print u"%s сконвертирован." % filePath
				except:
					print u"Ошибка в имени файла: название содержит русские символы."
			else :
				print u"Файл %s находится в кодировке %s и не требует конвертирования." % (filePath, enc)
			print '-'*40

if __name__ == '__main__':
	if len(sys.argv[1:]) == 0:
		try:
			path = raw_input(u"Input path or file:")
		except KeyboardInterrupt:
			print u"Ввод отменён."
			sys.exit(0)
	else:
		path = sys.argv[1:][0]
	if os.path.isdir(path):
		last = path[-1]
		if last.endswith('/'):
			path = path
		else :
			path = path+"/"
		print path
		for (path, dirs, files) in os.walk(path):
			for file in files:
				filePath = path+file
				filePath = filePath.decode("utf-8")
				converter(filePath)
	elif os.path.isfile(path) :
		converter(path)			
sys.exit(0)

Скрипт проверяет входной файл на кодировку, если файл в кодировке, отличной от UTF-8 — конвертирует файл. Для корректной работы скрипта нам необходим модуль chardet. Его нужно скачать, ну а дальше всё просто — разархивируем модуль, через консоль заходим в эту директорию, допустим:

cd ~/Downloads/chardet-2.1.1

и выполнить команду:

python setup.py install

модуль достаточно быстро установится и скрипт будет полностью работоспособен.
Скрипт способен конвертировать как одиночный файл, так и всю директорию целиком (находя в ней только файлы с расширением srt, ass, txt). Примеры:

python converter.py '~/Downloads/Новая папка/ansi.srt'
python converter.py '~/Downloads/Новая папка/'

Если вызвать скрипт без аргументов, то вы получите приглашение ввести путь к директории или файлу.

Пользуйтесь на здоровье.

Скрипт на github где жду ваших фиксов и дополнений.

#!/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(‘cant 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 cant be detected’, fg=«blue») print ‘Encoding cant 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()

45 / 39 / 24

Регистрация: 29.11.2013

Сообщений: 139

1

Как перекодировать строку?

21.12.2014, 18:13. Показов 18409. Ответов 6


Как перекодировать эту строку в читаемый вид из cp1251 в utf-8?

ÀÍÅÊÄÎÒ — Ñåìüÿ.Ìóëüò.Ïîäðîáíåå

__________________
Помощь в написании контрольных, курсовых и дипломных работ, диссертаций здесь



0



2738 / 2341 / 620

Регистрация: 19.03.2012

Сообщений: 8,832

21.12.2014, 18:30

2

Когда строка уже в виде крокозябр и начальная кодировка в которой все нормально отображается потеряна, то только с помощью сервисов типа http://www.artlebedev.ru/tools/decoder/



0



45 / 39 / 24

Регистрация: 29.11.2013

Сообщений: 139

21.12.2014, 18:39

 [ТС]

3

tsar925, А если начальная кодировка cp1251 ?



0



alex925

2738 / 2341 / 620

Регистрация: 19.03.2012

Сообщений: 8,832

21.12.2014, 18:45

4

Если в твоё приложение приходить строка в cp1251, то просто эту строку декодируешь во внутреннее представление строк (в utf8) и все.

Python
1
inp_str.decode('cp1251')



0



ivsatel

45 / 39 / 24

Регистрация: 29.11.2013

Сообщений: 139

21.12.2014, 19:06

 [ТС]

5

tsar925, Что-то делаю не так?

Python
1
2
a = "ÀÍÅÊÄÎÒ - Ñåìüÿ.Ìóëüò.Ïîäðîáíåå".encode('utf-8')
print(a.decode('cp1251'))

Кстати в браузере кракозябры четко преобразуются при сохранении поста.



0



2738 / 2341 / 620

Регистрация: 19.03.2012

Сообщений: 8,832

21.12.2014, 19:14

6

Вторая строка неправильная, у тебя за место cp1251 должно быть написано utf8, потому что метод decode принимает значение кодировки в которой закодирована строка сейчас.



1



ivsatel

45 / 39 / 24

Регистрация: 29.11.2013

Сообщений: 139

21.12.2014, 20:49

 [ТС]

7

Получилось вот так:

Python
1
print(inp_str.encode('latin1').decode('cp1251'))



0



Понравилась статья? Поделить с друзьями:
  • Python 3 кодировка utf 8 в windows 1251
  • Pytest windows fatal exception access violation
  • Pyserial python 3 работа с com портом windows
  • Pyren для windows скачать на русском
  • Pyren renault скачать бесплатно для windows