Зачем объявлять unicode по строке в python?
Я все еще изучаю python, и у меня есть сомнения:
В 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 по умолчанию, но ее можно переопределить с помощью объявления заголовка, так что точка объявления каждой строки?
Добавление: Похоже, что я перепутал кодировку файлов с строковой кодировкой. Спасибо, что объяснили это:)
Ответы
Ответ 1
Это две разные вещи, как упомянули другие.
Когда вы указываете # -*- coding: utf-8 -*-
, вы сообщаете Python, что исходный файл, который вы сохранили, utf-8
. По умолчанию для Python 2 используется ASCII (для Python 3 it utf-8
). Это просто влияет на то, как интерпретатор считывает символы в файле.
В общем, это, вероятно, не самая лучшая идея для встраивания высоких символов Юникода в ваш файл независимо от того, что такое кодировка; вы можете использовать строки unicode escapes, которые работают в любой кодировке.
Когда вы объявляете строку с 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'
, чтобы объявить последовательность байтов).
Ответ 2
Как говорили другие, # coding:
указывает кодировку, в которой сохранен исходный файл. Вот несколько примеров, чтобы проиллюстрировать это:
Файл, сохраненный на диске как cp437 (моя консольная кодировка), но не объявленная кодировка
b = 'über'
u = u'über'
print b,repr(b)
print u,repr(u)
Вывод:
File "C:\ex.py", line 1
SyntaxError: Non-ASCII character '\x81' in file C:\ex.py on line 1, but no
encoding declared; see http://www.python.org/peps/pep-0263.html for details
Добавлен вывод файла с # coding: cp437
:
über '\x81ber'
über u'\xfcber'
Сначала Python не знал кодировки и жаловался на символ, отличный от ASCII. Как только он узнал кодировку, байтовая строка получила байты, которые были на самом деле на диске. Для строки Unicode Python read\x81 знал, что в cp437, который был ü, и декодировал его в коде Unicode для ü, который является U + 00FC. Когда строка байтов была напечатана, Python отправил шестнадцатеричное значение 81
в консоль напрямую. Когда строка Unicode была напечатана, Python правильно обнаружил мою консольную кодировку как cp437 и перевел Unicode ü на значение cp437 для ü.
Здесь, что происходит с файлом, объявленным и сохраненным в UTF-8:
├╝ber '\xc3\xbcber'
über u'\xfcber'
В UTF-8 ü кодируется как шестнадцатеричные байты C3 BC
, поэтому строка байтов содержит эти байты, но строка Unicode идентична первому примеру. Python прочитал два байта и правильно декодировал его. Python неправильно напечатал байтовую строку, потому что он отправил два байта UTF-8, представляющие ü, прямо на консоль cp437.
Здесь файл объявлен cp437, но сохранен в UTF-8:
├╝ber '\xc3\xbcber'
├╝ber u'\u251c\u255dber'
В байтовой строке все еще есть байты на диске (UTF-8 hex bytes C3 BC
), но они интерпретируются как два символа cp437 вместо одного символа с кодировкой UTF-8. Те два символа, которые переведены в код Юникода, и все печатает неправильно.
Ответ 3
Это не устанавливает формат строки; он задает формат файла. Даже с этим заголовком "hello"
является байтовой строкой, а не строкой Unicode. Чтобы сделать его Unicode, вам придется использовать u"hello"
всюду. Заголовок - это лишь подсказка о том, какой формат использовать при чтении файла .py
.
Ответ 4
Определение заголовка должно определять кодировку самого кода, а не результирующие строки во время выполнения.
если в сценарии python вставить символ, отличный от ascii, например without, без определения заголовка utf-8, появится предупреждение
Ответ 5
если вы используете python 2, добавьте это: from __future__ import unicode_literals
Ответ 6
Я сделал следующий модуль с именем unicoder, чтобы можно было выполнять преобразование переменных:
import sys
import os
def ustr(string):
string = 'u"%s"'%string
with open('_unicoder.py', 'w') as script:
script.write('# -*- coding: utf-8 -*-\n')
script.write('_ustr = %s'%string)
import _unicoder
value = _unicoder._ustr
del _unicoder
del sys.modules['_unicoder']
os.system('del _unicoder.py')
os.system('del _unicoder.pyc')
return value
Тогда в вашей программе вы можете сделать следующее:
# -*- coding: utf-8 -*-
from unicoder import ustr
txt = 'Hello, Unicode World'
txt = ustr(txt)
print type(txt) # <type 'unicode'>