Я все еще изучаю питон и сомневаюсь:
В python 2.6.x я обычно объявляю кодировку в заголовке файла следующим образом (как в PEP 0263 )
# -*- coding: utf-8 -*-
После этого мои строки пишутся как обычно:
a = "A normal string without declared Unicode"
Но каждый раз, когда я вижу код проекта Python, кодировка не объявляется в заголовке. Вместо этого он объявляется в каждой строке следующим образом:
a = u"A string with declared Unicode"
Какая разница? Какая у этого цель? Я знаю, что Python 2.6.x устанавливает кодировку ASCII по умолчанию, но ее можно переопределить объявлением заголовка, так в чем смысл объявления каждой строки?
Приложение: Кажется, я перепутал кодировку файлов со строковой кодировкой. Спасибо, что объяснили :)
# coding: utf8
достаточно хорошо, в этом нет необходимости-*-
# coding: utf-8
.#coding=utf-8
. python.org/dev/peps/pep-0263Ответы:
Как отмечали другие, это две разные вещи.
Когда вы указываете
# -*- coding: utf-8 -*-
, вы сообщаете Python, что сохраненный вами исходный файлutf-8
. По умолчанию для Python 2 используется ASCII (для Python 3 этоutf-8
). Это просто влияет на то, как интерпретатор читает символы в файле.В общем, вероятно, не лучшая идея встраивать символы Юникода в ваш файл независимо от кодировки; вы можете использовать строковые escape-последовательности Unicode, которые работают в любой кодировке.
Когда вы объявляете строку с символом
u
впереди , напримерu'This is a string'
, она сообщает компилятору Python, что строка является Unicode, а не байтами. Это обрабатывается интерпретатором в основном прозрачно; наиболее очевидное отличие состоит в том, что теперь вы можете вставлять символы Юникода в строку (тоu'\u2665'
есть теперь это разрешено). Вы можете использоватьfrom __future__ import unicode_literals
его по умолчанию.Это применимо только к Python 2; в Python 3 по умолчанию используется Unicode, и вам нужно указать
b
перед ним (напримерb'These are bytes'
, для объявления последовательности байтов).источник
Как уже говорили другие,
# coding:
указывает кодировку, в которой сохраняется исходный файл. Вот несколько примеров, чтобы проиллюстрировать это:Файл сохранен на диске как cp437 (моя кодировка консоли), но не объявлена кодировка
Вывод:
Вывод файла с
# coding: cp437
добавленными:Сначала Python не знал кодировки и жаловался на символ, отличный от ASCII. Как только он узнал кодировку, байтовая строка получила байты, которые действительно были на диске. Для строки Unicode Python читал \ x81, знал, что в cp437 это был ü , и декодировал его в кодовую точку Unicode для ü, которая является U + 00FC. Когда байтовая строка была напечатана, Python отправил шестнадцатеричное значение
81
непосредственно на консоль. Когда строка Unicode была напечатана, Python правильно определил мою кодировку консоли как cp437 и преобразовал Unicode ü в значение cp437 для ü .Вот что происходит с файлом, объявленным и сохраненным в UTF-8:
В UTF-8 ü кодируется как шестнадцатеричные байты
C3 BC
, поэтому строка байтов содержит эти байты, но строка Unicode идентична первому примеру. Python прочитал два байта и правильно их декодировал. Python напечатал байтовую строку неправильно, потому что он отправил два байта UTF-8, представляющие ü, прямо на мою консоль cp437.Здесь файл объявлен cp437, но сохранен в UTF-8:
Строка байтов все еще
C3 BC
содержит байты на диске (шестнадцатеричные байты UTF-8 ), но интерпретирует их как два символа cp437 вместо одного символа в кодировке UTF-8. Эти два символа были переведены в кодовые точки Unicode, и все печатается неправильно.источник
Это не устанавливает формат строки; он устанавливает формат файла. Даже с этим заголовком
"hello"
это строка байтов, а не строка Unicode. Чтобы сделать его Unicode, вам придется использоватьu"hello"
везде. Заголовок - это всего лишь намек на то, какой формат использовать при чтении.py
файла.источник
Определение заголовка должно определять кодировку самого кода, а не результирующих строк во время выполнения.
размещение символа, отличного от ascii, например ۲, в скрипте python без определения заголовка utf-8 вызовет предупреждение
источник
Я сделал следующий модуль под названием unicoder, чтобы иметь возможность выполнять преобразование переменных:
Тогда в своей программе вы можете сделать следующее:
источник