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

Как поменять кодировку в питоне

  • автор:

Кодировки в 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 

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

Как поменять кодировку файла в python на UNF-8-BOM без \ufeff?

Пишу скрипт, который автоматически переведёт игру. Вся локализация игры лежит в файле с кодировкой utf-8-bom. Я перевожу и записываю перевод в файл, который тоже должен быть utf-8-bom, но python настойчиво делает из него обычный utf-8, чтобы перевести его в bom я создал такую функцию:

def encod_utf8_bom(self, path_on_file: str): file = open(path_on_file, encoding='utf-8', mode='r') encoding_file = [line.encode('utf-8-sig') for line in file] file.close() file = open(path_on_file, 'wb') [file.write(line) for line in encoding_file] file.close()

60f4a3c802081200335687.jpeg

Но она ставит \ufeff впереди (отображается как точка впереди)
И в итоге перевод не работает. Однако если я сделаю перевод на utf-8 и через Notepad ++ сменю кодировку на utf-8-bom перевод заработает (и отображается без точек). Как мне сделать так же но в python?

  • Вопрос задан более двух лет назад
  • 550 просмотров

Напоминание

Для понимания материала ОБЯЗАТЕЛЬНО каждый пример пытаться исполнить, понять, почему он работает или не работает, и попробовать в нём что-то поменять, и посмотреть, что получится.

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

Что такое текстовый файл

С точки зрения операционной системы, и, следовательно, питона, файл – это последовательность байт. (Можно считать, что один байт – это одно число от 0 до 255, то есть если бы у нас был алфавит из 256 букв, то файл из N байт – это N букв этого алфавита).

Общепринято нестрогое и неформальное деление файлов на текстовые и бинарные.

В текстовом файле последовательность байт несёт единственный смысл: последовательность букв текста в человеческом понимании. (В простейшем виде действует соотношение: один байт – одна буква). Т.е. в текстовом файле кроме текста нет ничего. Простейший пример текстового файла – текст, набранный в notepad (он же блокнот) в windows.

В бинарном файле, в зависимости от типа файла (например, картинка JPEG, ролик MKV, документ DOC, архив ZIP) разным байтам придаётся разный смысл: какие-то трактуются как числа, какие-то обозначают яркость канала цвета, какие-то громкость звука. Если бы мы попытались открыть бинарный файл текстовым редактором (например, notepad), то мы увидим непонятную ерунду: потому, что мы те же байты пытаемся интерпретировать с точки зрения другого языка. (Как пытаться расслышать русские слова в китайской речи).

Начиная с этого занятия мы обнаружим, что в питоне гораздо проще общаться с текстовыми файлами.

Понятие кодировки

Кодировка текста – это правила, которые устанавливают, какие байты соответствуют какой букве.

Очень важная кодировка – ASCII. Это одна из довольно старых кодировок, она стандартизована в Америке в 1963 году, и она приписывает 128 различным значениям байта буквы, цифры, и основные знаки пунктуации. В этой кодировке один байт обозначает одну букву, но для некоторых значений байта начертание не определено.

  • cp866, она же DOS
  • cp1251, она же windows-1251
  • koi8-r

Во всех этих кодировках байты с числовыми значениями от 0 до 127 совпадают с ASCII, а остальным значениям приписаны русские буквы (притом везде разными, никак друг на друга не похожими способами).

Для языков, которые используют китайские иероглифы, сделать кодировку с отображением один байт = один символ невозможно, поэтому китайцы, японцы и корейцы посочиняли для себя кодировок, где один иероглиф задаётся последовательностью из двух-четырёх байт рядом.

Всего таких кодировок образовалось порядка тысячи. А для того, чтобы иметь возможность между ними конвертировать тексты, нужно (задача по математике – сколько?) перекодировщиков.

Поэтому в конце 80-х годов возник The Unicode Consortium, который стал собирать реестр всех символов, которые возможно представлять в компьютере. Этот реестр стал называться Unicode.

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

  • utf-8 – это наиболее популярная кодировка сейчас. Она замечательна тем, что для английского текста она совпадает с ASCII (и, соответственно, действует соответствие 1 байт = 1 буква), для русского, греческого, абабского и т.п. в ней действует соответствие 1 буква = 2 байта, а для иероглифов и совсем экзотических символов соотношение становится 1 буква = 3 байта.
  • utf-16 и utf-32 – это способы представлять наиболее употребимую часть реестра уникода в 2 или 4 байта соответственно.

Два типа строк в питоне

Строки, с которыми мы до сих пор работали в питоне, на самом деле были просто списками байтов. Для кодировки ASCII или других однобайтовых кодировок получается только одна беда – мы будем на экран писать те же байты, что и в тексте программы, а если экран отображает другую кодировку, чем в тексте программы, то мы увидим крякозябликов. А для многобайтных кодировок у нас будут получаться ещё и странные результаты про длину строк (количество байт) – она будет оказываться больше, чем количество символов в ней – поэтому я и советовал избегать русского языка.

Уникодовская идея о том, что внутри программы любой текст должен иметь универсальное представление, не зависимое от кодировки – правильная. Питон позволяет этой идеей пользоваться. Для этого в питоне есть ещё один тип строк – это «уникодовские строки».

Уникодовские строки обозначаются в питоне префиксом u перед открывающей кавычкой строки:

 1  print u"Привет" 

Так как даже при прочтении программы питон должен раскодировать её текст и превратить его в универсальное представление, мы должны ему сообщить о том, в какой кодировке хранится текст программы. Для этого нужно в одной из первых двух строк программы добавить комментарий с текстом: coding: имя кодировки. Редактор IDLE добавляет такой комментарий самостоятельно, если только у вас в тексте программы есть не-английские буквы.

  • строка в какой-то кодировке -> decode -> уникодная строка
  • уникодная строка -> encode -> строка в какой-то кодировке
 1  # coding: cp1251  2  s = "Привет"  3  u = s.decode("cp1251") # сработает, если у вас кодировка cp1251  4  s2 = u.encode("cp1251")  5  print s2 

Кроме того, в питоне команда print самостоятельно переводит уникодные строки в кодировку экрана.

Как прочитать и записать файл в питоне

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

  • побайтовый – тогда файл открывается функцией open() – в этом случае все функции чтения возвращают обычные строки, а если в файле лежит текст, то за конвертирование кодировок отвечает сам автор программы
  • уникодный – тогда файл открывается функцией codecs.open() – в этом случае питон берёт на себя заботу о кодировках и возвращает в программу уникодные строки

Нас, очевидно, будет интересовать всегда второй способ.

Обе функции первым аргументом получают имя файла. Вторым аргументом – режим работы с файлом: букву ‘r’, если мы хотим файл только читать, ‘w’, если мы хотим в файл только писать. codecs.open имеет ещё и третий аргумент, которым мы указываем, кодировку текста в файле.

Открыв файл, мы получаем файловый объект, вызывая методы которого мы можем что-то делать с файлом.

Самое простое, что можно сделать с файлом – это его открыть и получить весь его текст в виде одной гигантской строки. Для этого у файловых объектов есть метод read:

 1  import codecs  2  file = codecs.open("hello.txt", "r", "utf-8")  3  contents = file.read()  4  print contents 

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

При общении с файлом у питона всегда есть понятие курсора, как в текстовом редакторе. read читает весь файл от текущего места (которое изначально в начале файла) и переводит курсор в конец файла, так что если мы вызовем read ещё раз, на следующий раз он нам вернёт пустую строку.

Самая частая практическая потребность от файлов – это чтение по строкам. Поэтому в питоне сам объект файла является итератором, идущим по строкам файла. (Если убрать слово итератор, то это утверждение полностью эквивалентно такому: если файл запихать в цикл for, то цикл for будет идти по строкам файла, если файл дать аргументом функции list(), то list() вернёт нам список строк в файле):

 1  import codecs  2  file = codecs.open("hello.txt", "r", "utf-8")  3  for line in file:  4  print len(line), line 

Если мы хотим записать текст в файл:

 1  import codecs  2  file = codecs.open("hello.txt", "w", "utf-8")  3  file.write("Hello,")  4  file.write(" ")  5  file.write("world!\n")  6  file.close() 
  • мы должны указать, что открываем файл для чтения
  • при этом в момент открытия питон создаст такой файл, если его ещё не было, и сотрёт содержимое этого файла, если он уже существовал! Обратите на это внимание: питон не будет спрашивать вас, уверены ли вы в том, что вы хотите стереть этот файл, он его просто сотрёт!
  • для записи в файл мы вызываем метод write, который дописывает наш текст в конец файла.
  • метод write не добавляет перенос строки, поэтому мы должны об этом позабоититься сами и дописать в конец строки ‘\n’
  • символ ‘\n’ в питоне обозначает обычный конец строки
  • чтобы данные оказались у нас на диске, мы должны закрыть файл методом close (здесь история точно такая же как с вытаскиванием флэшки из компьютера: если вы не закроете файл, зачастую у вас всё запишется как нужно, и только в самый ответственный момент окажется, что вы создали пустой файл. За этим тщательно следит Мэрфи)

Бдительный читатель справедливо заподозрит, что sys.stdout, которым мы пользовались на первом занятии, на самом деле есть ни что иное как виртуальный файл, содержимое которого сразу оказывается на экране. Однако я повторяю призыв, что печатать на экран проще с помощью команды print, и давайте мы только ей для этого и будем пользоваться.

Литература

  • http://docs.python.org/2.7/tutorial/introduction.html#unicode-strings
  • http://docs.python.org/2.7/tutorial/inputoutput.html#reading-and-writing-files

как изменить кодировку скрипта на python?

Как мне перекодировать код? Ошибка в pyinstaller с кодировкой, мне сказали, что нужно перекодировать код.

Отслеживать
задан 10 мая 2020 в 5:32
POLTERGEIST POLTERGEIST
13 5 5 бронзовых знаков

1 ответ 1

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

В начала скрипта добавь: # -*- coding: utf-8 -*- . Или вместо utf-8 другую кодировку введи (которая тебе нужна).

Отслеживать
ответ дан 10 мая 2020 в 6:10
372 1 1 серебряный знак 10 10 бронзовых знаков
я это делал, мне не помогало
10 мая 2020 в 6:38

mb4.ru/18-text-editors/notepad/… Левый гайд, но суть понятна. anton-pribora.ru/recoder или используй подобные программы. Чтобы дать более развернутый ответ, хотелось бы увидеть ТрэшБэк ошибки и команду которая его вызывает.

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

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