Convert windows 1251 to utf 8 python

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’)

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

#!/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()

Python String encode() converts a string value into a collection of bytes, using an encoding scheme specified by the user.

Python String encode() Method Syntax:

Syntax: encode(encoding, errors)

Parameters: 

  • encoding: Specifies the encoding on the basis of which encoding has to be performed. 
  • errors: Decides how to handle the errors if they occur, e.g ‘strict’ raises Unicode error in case of exception and ‘ignore’ ignores the errors that occurred. There are six types of error response
    • strict – default response which raises a UnicodeDecodeError exception on failure
    • ignore – ignores the unencodable unicode from the result
    • replace – replaces the unencodable unicode to a question mark ?
    • xmlcharrefreplace – inserts XML character reference instead of unencodable unicode
    • backslashreplace – inserts a uNNNN escape sequence instead of unencodable unicode
    • namereplace – inserts a N{…} escape sequence instead of unencodable unicode

Return:  Returns the string in the encoded form

Python String encode() Method Example:

Python3

print("¶".encode('utf-8'))

Output:

b'xc2xb6'

Example 1: Code to print encoding schemes available

There are certain encoding schemes supported by Python String encode() method. We can get the supported encodings using the Python code below.

Python3

from encodings.aliases import aliases

print("The available encodings are : ")

print(aliases.keys())

Output: 

The available encodings are : 
dict_keys(['ibm039', 'iso_ir_226', '1140', 'iso_ir_110', '1252', 'iso_8859_8', 'iso_8859_3', 'iso_ir_166', 'cp367', 'uu', 'quotedprintable', 'ibm775', 'iso_8859_16_2001', 'ebcdic_cp_ch', 'gb2312_1980', 'ibm852', 'uhc', 'macgreek', '850', 'iso2022jp_2', 'hz_gb_2312', 'elot_928', 'iso8859_1', 'eucjp', 'iso_ir_199', 'ibm865', 'cspc862latinhebrew', '863', 'iso_8859_5', 'latin4', 'windows_1253', 'csisolatingreek', 'latin5', '855', 'windows_1256', 'rot13', 'ms1361', 'windows_1254', 'ibm863', 'iso_8859_14_1998', 'utf8_ucs2', '500', 'iso8859', '775', 'l7', 'l2', 'gb18030_2000', 'l9', 'utf_32be', 'iso_ir_100', 'iso_8859_4', 'iso_ir_157', 'csibm857', 'shiftjis2004', 'iso2022jp_1', 'iso_8859_2_1987', 'cyrillic', 'ibm861', 'ms950', 'ibm437', '866', 'csibm863', '932', 'iso_8859_14', 'cskoi8r', 'csptcp154', '852', 'maclatin2', 'sjis', 'korean', '865', 'u32', 'csshiftjis', 'dbcs', 'csibm037', 'csibm1026', 'bz2', 'quopri', '860', '1255', '861', 'iso_ir_127', 'iso_celtic', 'chinese', 'l8', '1258', 'u_jis', 'cspc850multilingual', 'iso_2022_jp_2', 'greek8', 'csibm861', '646', 'unicode_1_1_utf_7', 'ibm862', 'latin2', 'ecma_118', 'csisolatinarabic', 'zlib', 'iso2022jp_3', 'ksx1001', '858', 'hkscs', 'shiftjisx0213', 'base64', 'ibm857', 'maccentraleurope', 'latin7', 'ruscii', 'cp_is', 'iso_ir_101', 'us_ascii', 'hebrew', 'ansi_x3.4_1986', 'csiso2022jp', 'iso_8859_15', 'ibm860', 'ebcdic_cp_us', 'x_mac_simp_chinese', 'csibm855', '1250', 'maciceland', 'iso_ir_148', 'iso2022jp', 'u16', 'u7', 's_jisx0213', 'iso_8859_6_1987', 'csisolatinhebrew', 'csibm424', 'quoted_printable', 'utf_16le', 'tis260', 'utf', 'x_mac_trad_chinese', '1256', 'cp866u', 'jisx0213', 'csiso58gb231280', 'windows_1250', 'cp1361', 'kz_1048', 'asmo_708', 'utf_16be', 'ecma_114', 'eucjis2004', 'x_mac_japanese', 'utf8', 'iso_ir_6', 'cp_gr', '037', 'big5_tw', 'eucgb2312_cn', 'iso_2022_jp_3', 'euc_cn', 'iso_8859_13', 'iso_8859_5_1988', 'maccyrillic', 'ks_c_5601_1987', 'greek', 'ibm869', 'roman8', 'csibm500', 'ujis', 'arabic', 'strk1048_2002', '424', 'iso_8859_11_2001', 'l5', 'iso_646.irv_1991', '869', 'ibm855', 'eucjisx0213', 'latin1', 'csibm866', 'ibm864', 'big5_hkscs', 'sjis_2004', 'us', 'iso_8859_7', 'macturkish', 'iso_2022_jp_2004', '437', 'windows_1255', 's_jis_2004', 's_jis', '1257', 'ebcdic_cp_wt', 'iso2022jp_2004', 'ms949', 'utf32', 'shiftjis', 'latin', 'windows_1251', '1125', 'ks_x_1001', 'iso_8859_10_1992', 'mskanji', 'cyrillic_asian', 'ibm273', 'tis620', '1026', 'csiso2022kr', 'cspc775baltic', 'iso_ir_58', 'latin8', 'ibm424', 'iso_ir_126', 'ansi_x3.4_1968', 'windows_1257', 'windows_1252', '949', 'base_64', 'ms936', 'csisolatin2', 'utf7', 'iso646_us', 'macroman', '1253', '862', 'iso_8859_1_1987', 'csibm860', 'gb2312_80', 'latin10', 'ksc5601', 'iso_8859_10', 'utf8_ucs4', 'csisolatin4', 'ebcdic_cp_be', 'iso_8859_1', 'hzgb', 'ansi_x3_4_1968', 'ks_c_5601', 'l3', 'cspc8codepage437', 'iso_8859_7_1987', '8859', 'ibm500', 'ibm1026', 'iso_8859_6', 'csibm865', 'ibm866', 'windows_1258', 'iso_ir_138', 'l4', 'utf_32le', 'iso_8859_11', 'thai', '864', 'euc_jis2004', 'cp936', '1251', 'zip', 'unicodebigunmarked', 'csHPRoman8', 'csibm858', 'utf16', '936', 'ibm037', 'iso_8859_8_1988', '857', 'csibm869', 'ebcdic_cp_he', 'cp819', 'euccn', 'iso_8859_2', 'ms932', 'iso_2022_jp_1', 'iso_2022_kr', 'csisolatin6', 'iso_2022_jp', 'x_mac_korean', 'latin3', 'csbig5', 'hz_gb', 'csascii', 'u8', 'csisolatin5', 'csisolatincyrillic', 'ms_kanji', 'cspcp852', 'rk1048', 'iso2022jp_ext', 'csibm273', 'iso_2022_jp_ext', 'ibm858', 'ibm850', 'sjisx0213', 'tis_620_2529_1', 'l10', 'iso_ir_109', 'ibm1125', '1254', 'euckr', 'tis_620_0', 'l1', 'ibm819', 'iso2022kr', 'ibm367', '950', 'r8', 'hex', 'cp154', 'tis_620_2529_0', 'iso_8859_16', 'pt154', 'ebcdic_cp_ca', 'ibm1140', 'l6', 'csibm864', 'csisolatin1', 'csisolatin3', 'latin6', 'iso_8859_9_1989', 'iso_8859_3_1988', 'unicodelittleunmarked', 'macintosh', '273', 'latin9', 'iso_8859_4_1988', 'iso_8859_9', 'ebcdic_cp_nl', 'iso_ir_144'])

Example 2: Code to encode the string

Python3

string = "¶" 

print(string.encode('utf-8'))

Output:

b'xc2xb6'

Errors when using wrong encoding scheme

Example 1: Python String encode() method will raise UnicodeEncodeError if wrong encoding scheme is used

Python3

string = "¶" 

print(string.encode('ascii'))

Output:

UnicodeEncodeError: 'ascii' codec can't encode character 'xb6' in position 0: ordinal not in range(128)

Example 2: Using ‘errors’ parameter to ignore errors while encoding

Python String encode() method with errors parameter set to ‘ignore’ will ignore the errors in conversion of characters into specified encoding scheme.

Python3

string = "123-¶" 

print(string.encode('ascii', errors='ignore'))

Output:

b'123-'

Я, и пожалуй это не удивительно, люблю аниме, как и многие в современном мире. Единственное — терпеть не могу русскую озвучку и предпочитаю смотреть с субтитрами. Но…большинство релизеров сидят на 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 где жду ваших фиксов и дополнений.

45 / 39 / 24

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

Сообщений: 139

1

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

21.12.2014, 18:13. Показов 18395. Ответов 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



1. Summary

I can’t find, how I can to refactor multiple with open for one file.


2. Expected behavior of program

Program detect encoding for each file in the directory. If encoding ≠ UTF-8, file convert to UTF-8.


3. Minimal example of working code

(I’m sorry, Repl.it and another online Python interpreters incorrect works with non-UTF-8 files. But just in case, I created an online demonstration.)

  • kira_encoding.py
# @Author: SashaChernykh
# @Date: 2018-09-01 13:31:06
# @Last Modified time: 2018-09-01 14:39:30
"""kira_encoding module."""
import codecs
import glob

import chardet

ALL_FILES = glob.glob('*.md')


def kira_encoding_function():
    """Check encoding and convert to UTF-8, if encoding no UTF-8."""
    for filename in ALL_FILES:

        # Not 100% accuracy:
        # https://stackoverflow.com/a/436299/5951529
        # Check:
        # https://chardet.readthedocs.io/en/latest/usage.html#example-using-the-detect-function
        # https://stackoverflow.com/a/37531241/5951529
        with open(filename, 'rb') as opened_file:
            bytes_file = opened_file.read()
            chardet_data = chardet.detect(bytes_file)
            fileencoding = (chardet_data['encoding'])
            print('fileencoding', fileencoding)

            if fileencoding in ['utf-8', 'ascii']:
                print(filename + ' in UTF-8 encoding')
            else:
                # Convert file to UTF-8:
                # https://stackoverflow.com/a/191403/5951529
                with codecs.open(filename, 'r') as file_for_conversion:
                    read_file_for_conversion = file_for_conversion.read()
                with codecs.open(filename, 'w', 'utf-8') as converted_file:
                    converted_file.write(read_file_for_conversion)
                print(filename +
                      ' in ' +
                      fileencoding +
                      ' encoding automatically converted to UTF-8 ')


kira_encoding_function()
  • Kira1.md in UTF-8:
Kira Goddess!
  • Kira2.md in Cyrillic-1251:
Кира Богиня!
  • Kira3.md in Central European Cyrillic 1250:
Kiara Istennő!

4. Problem

I use with 3 times for opening same file. I don’t think, that is a good practice.

Radon Cyclomatic Complexity not A:

D:SashaDebuggingKiraEncoding>radon cc kira_encoding.py
kira_encoding.py
    F 13:0 kira_encoding_function - B

I can not use with, but it anti-pattern.


5. Not helped

5.1. Modes

  • That get encoding via chardet I need rb — bytes mode;
  • That convert file via codecs I need non-bytes modes.

I can’t find, what can I do, that to have same mode for these actions.

5.2. decode

I can remove 1 with, if I know file encoding.

cyrillic_file = bytes_file.decode('cp1251')
with codecs.open(filename, 'w', 'utf-8') as converted_file:
    converted_file.write(cyrillic_file)
  • Full file:
# @Author: SashaChernykh
# @Date: 2018-09-01 13:31:06
# @Last Modified time: 2018-09-01 16:26:57
"""kira_encoding module."""
import codecs
import glob

import chardet

ALL_FILES = glob.glob('*.md')

def kira_encoding_function():
    """Check encoding and convert to UTF-8, if encoding no UTF-8."""
    for filename in ALL_FILES:

        # Not 100% accuracy:
        # https://stackoverflow.com/a/436299/5951529
        # Check:
        # https://chardet.readthedocs.io/en/latest/usage.html#example-using-the-detect-function
        # https://stackoverflow.com/a/37531241/5951529
        with open(filename, 'rb') as opened_file:
            bytes_file = opened_file.read()
            chardet_data = chardet.detect(bytes_file)
            fileencoding = (chardet_data['encoding'])
            print('fileencoding', fileencoding)

            if fileencoding in ['utf-8', 'ascii']:
                print(filename + ' in UTF-8 encoding')
            else:
                # Convert file to UTF-8:
                # https://stackoverflow.com/q/19932116/5951529
                cyrillic_file = bytes_file.decode('cp1251')
                with codecs.open(filename, 'w', 'utf-8') as converted_file:
                    converted_file.write(cyrillic_file)
                print(filename +
                      ' in ' +
                      fileencoding +
                      ' encoding automatically converted to UTF-8')


kira_encoding_function()

But the files may not necessarily be in Cyrillic-1251, they can be in any encoding. I can’t find, How can I decode from any encoding. For example, this can’t work:

>>> kiragoddess = b'xcaxe8xf0xe0 xc1xeexe3xe8xedxff!'
>>> kiragoddess.decode('cp1251')
'Кира Богиня!'
>>> kiragoddess.decode()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
UnicodeDecodeError: 'utf-8' codec can't decode byte 0xca in position 0: invalid continuation byte

5.3. Nested syntax

Nested syntax doesn’t work for me. If:

with codecs.open(filename, 'r') as file_for_conversion, codecs.open(filename, 'w', 'utf-8') as converted_file:
    read_file_for_conversion = file_for_conversion.read()
    converted_file.write(read_file_for_conversion)
  • Full file:
# @Author: SashaChernykh
# @Date: 2018-09-01 13:31:06
# @Last Modified time: 2018-09-01 16:01:29
"""kira_encoding module."""
import codecs
import glob

import chardet

ALL_FILES = glob.glob('*.md')


def kira_encoding_function():
    """Check encoding and convert to UTF-8, if encoding no UTF-8."""
    for filename in ALL_FILES:

        # Not 100% accuracy:
        # https://stackoverflow.com/a/436299/5951529
        # Check:
        # https://chardet.readthedocs.io/en/latest/usage.html#example-using-the-detect-function
        # https://stackoverflow.com/a/37531241/5951529
        with open(filename, 'rb') as opened_file:
            bytes_file = opened_file.read()
            chardet_data = chardet.detect(bytes_file)
            fileencoding = (chardet_data['encoding'])
            print('fileencoding', fileencoding)

            if fileencoding in ['utf-8', 'ascii']:
                print(filename + ' in UTF-8 encoding')
            else:
                # Convert file to UTF-8:
                # https://stackoverflow.com/a/191403/5951529
                with codecs.open(filename, 'r') as file_for_conversion, codecs.open(filename, 'w', 'utf-8') as converted_file:
                    read_file_for_conversion = file_for_conversion.read()
                    converted_file.write(read_file_for_conversion)
                print(filename +
                      ' in ' +
                      fileencoding +
                      ' encoding automatically converted to UTF-8')


kira_encoding_function()

Content of non-UTF-8 files will be removed in this case.

6. Do not offer

  1. Yes, I know that I need to use logging, not print in real programs. Please, do not offer it; my question not about it.
  2. I need in-place conversion; my program must convert to UTF-8 to the same file, not to another.

В 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 = ╨в╨╡╨║╤Б╤В ╨▓ utf8

a2 = Текст в utf8

b = Текст в 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 = Текст в utf8

b = Текст в unicode

c = Текст в 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 [‘xd0xa2xd0xb5xd1x81xd1x82’, ‘xd1x81xd0xbfxd0xb8xd1x81xd0xbaxd0xb0’]

2 [‘xd0xa2xd0xb5xd1x81xd1x82’, ‘xd1x81xd0xbfxd0xb8xd1x81xd0xbaxd0xb0’]

3 Тест,списка

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

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

PYTHONIOENCODING=utf8 python 1.py

В обучении ребенка важно правильное толкование окружающего его мира. Существует масса полезных журналов которые начнут экологическое воспитание дошкольников правильным путем. Развивать интерес к окружающему миру очень трудный но интересный процесс, уделите этому особое внимание.

Понравилась статья? Поделить с друзьями:
  • Convert utf8 to windows 1251 powershell
  • Convert utf8 to windows 1251 php
  • Convert utf 8 to windows 1251 online
  • Convert unix path to windows path
  • Convert to gpt при установке windows