Зачем объявлять 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, появится предупреждение

error

Ответ 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'>