Зачем объявлять Unicode за строкой в ​​Python? - PullRequest
116 голосов
/ 03 июля 2010

Я все еще изучаю 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 по умолчанию, но она может быть переопределена объявлением заголовка, так какой смысл в объявлении строки?

Добавление: Кажется, что яперепутал кодирование файлов со строковым кодированием.Спасибо за объяснение:)

Ответы [ 5 ]

157 голосов
/ 03 июля 2010

Это две разные вещи, как уже упоминали другие.

Когда вы указываете # -*- coding: utf-8 -*-, вы говорите Python, что исходный файл, который вы сохранили - utf-8. По умолчанию для Python 2 используется ASCII (для Python 3 это utf-8). Это только влияет на то, как интерпретатор читает символы в файле.

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


Когда вы объявляете строку с 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', чтобы объявить последовательность байтов).

22 голосов
/ 03 июля 2010

Как уже говорили другие, # 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 прочитал \ 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 C3 BC), но интерпретирует их как два символа cp437 вместо одного символа в кодировке UTF-8. Те два символа, которые переведены в код Unicode, указывают, что все печатается неправильно.

10 голосов
/ 03 июля 2010

Это не устанавливает формат строки;устанавливает формат файла.Даже с этим заголовком "hello" является байтовой строкой, а не строкой Юникода.Чтобы сделать его Unicode, вы должны будете использовать u"hello" везде.Заголовок - это просто подсказка, какой формат использовать при чтении файла .py.

7 голосов
/ 03 июля 2010

Определение заголовка состоит в том, чтобы определить кодировку самого кода, а не результирующих строк во время выполнения.

помещение символа, отличного от ascii, такого как ۲ в сценарии python без определения заголовка utf-8, приведет кпредупреждение ошибка http://www.freeimagehosting.net/uploads/1ed15124c4.jpg

0 голосов
/ 10 мая 2018

Я сделал следующий модуль под названием 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'>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...