Кодировка Python - есть ли объяснение? - PullRequest
3 голосов
/ 09 марта 2012

Может кто-нибудь объяснить мне, почему Python имеет такое поведение?

Позвольте мне объяснить.

ПРЕДПОСЫЛКИ

У меня есть установка Python и яхочу использовать некоторые символы, которых нет в таблице ASCII.Таким образом, я изменяю свой python по умолчанию.Я сохраняю каждую строку в файле .py таким образом '_MAIL_TITLE_': u'Бронирование номеров',

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

Я помещаю в заголовок HTML-страницы:

<head>
 <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
 ...... <!-- Some Css's --> 
</head>

К сожалению, мой HTML-документ приходит ко мне (после замены) с некоторыми неправильными символами (не преобразованными? Неправильно преобразованными?)

Итак, я открываю терминал и начинаю делать заказ:

 1 - Python 2.4.6 (#1, Jan 27 2012, 15:41:03)
 2 - [GCC 4.1.2 20080704 (Red Hat 4.1.2-51)] on linux2
 3 - Type "help", "copyright", "credits" or "license" for more information.
 4 - >>> import sys
 5 - >>> sys.getdefaultencoding()
 6 - 'utf-8'
 7 - >>> u'èéòç'
 8 - u'\xe8\xe9\xf2\xe7'
 9 - >>> u'èéòç'.encode('utf-8')
10 - '\xc3\xa8\xc3\xa9\xc3\xb2\xc3\xa7'
11 - >>> u'è'
12 - u'\xe8'
13 - >>> u'è'.encode()
14 - '\xc3\xa8'

ВОПРОС

Взгляните на строку [7-10].Разве это не странно?Почему, если мой python (строка 6) имеет код по умолчанию utf-8, он преобразует эту строку (line7) не так, как строка 9?Теперь взгляните на строки [11-14] и их вывод.

Теперь я в полном замешательстве!

Подсказка

Итак, я попытался изменить свой способ ввода входных файлов (ранее ISO-8859-1 , теперь utf-8 ) и что-то изменилось:

 1 - Python 2.4.6 (#1, Jan 27 2012, 15:41:03)
 2 - [GCC 4.1.2 20080704 (Red Hat 4.1.2-51)] on linux2
 3 - Type "help", "copyright", "credits" or "license" for more information.
 4 - >>> import sys
 5 - >>> sys.getdefaultencoding()
 6 - 'utf-8'
 7 - >>> u'èéòç'
 8 - u'\xc3\xc3\xa8\xc3\xa9\xc3\xb2\xc3\xa7'
 9 - >>> u'èéòç'.encode('utf-8')
10 - '\xc3\xa8\xc3\xa9\xc3\xb2\xc3\xa7'
11 - >>> u'è'
12 - u'\xe8'
13 - >>> u'è'.encode()
14 -'\xc3\xa8'

Итак, кодировка (явное кодирование) работает независимо от входной кодировки (или мне кажется, но я застрял на этом на несколько дней, так что, возможно, я запутался).

ГДЕ РЕШЕНИЕ ??

Глядя на строки 8 из background и hint, вы можете увидеть, что существуют некоторые отличия созданного объекта Unicode.Итак, я начал думать об этом.Что я сделал вывод?Ничего такого.Ничего, кроме того, что, может быть, мои проблемы с кодировкой - это в кодировку файла, как только сохранить мой .py (который содержит все символы utf-8, которые должны быть вставлены в HTML-документ)

«РЕАЛЬНЫЙ» КОД

Код не делает ничего особенного: он открывает HTML-шаблон, помещает его в строку, заменяет заполнители на строки Юникода (utf-8ed? Wish yes) и сохраняетэто в другой файл, который будет визуализирован из Интернета (да, моя «целевая» страница содержит спецификации заголовка utf-8).У меня нет кода здесь, потому что он разбит на несколько файлов, но я уверен в рабочем процессе программы (отслеживая его).

ЗАКЛЮЧИТЕЛЬНЫЙ ВОПРОС

В свете этого, есть ли у кого-нибудь идея заставить мой код работать?Идеи о кодировке Unix файлов?Или .py кодировка файла?Как я могу изменить кодировку, чтобы мой код работал?

LAST HINT

Перед заменой заполнителей на объект utf-8, если я вставлю

utf8Obj.encode('latin-1')

мой документ отлично виден для Интернета!

Спасибо тем, кто отвечает.

РЕДАКТИРОВАТЬ1 - РАБОЧИЙ ПРОЦЕСС РАЗРАБОТКИ

ОКВот мой рабочий процесс разработки:

У меня есть CVS для этого проекта.Проект расположен на ОС Centos.Этот сервер является 64-битной машиной.Я разрабатываю свой код в Windows 7 (64-разрядная версия) с затмением.Каждая модификация совершается ТОЛЬКО с фиксацией CVS.Код распространяется на машину Centos, которая использует этот тип Python:

Python 2.4.6 (#1, Jan 27 2012, 15:41:03)
[GCC 4.1.2 20080704 (Red Hat 4.1.2-51)] on linux2

Я настроил Eclipse для работы таким образом: ПРЕДПОЧТЕНИЯ -> ОБЩИЕ -> РАБОЧЕЕ МЕСТО -> КОДИРОВАНИЕ ТЕКСТА ФАЙЛА: UTF-8

Приложение Zope / Plone запускается на том же сервере: оно обслуживает некоторые страницы PHP.Страницы PHP вызывают некоторые методы Python (логику приложения) от WS, которые расположены на «сервере» Zope / Plone.Интерфейс этого сервера напрямую связан с логикой приложения.

Вот и все

EDIT2

Эта функция заменяет:

    def _fillTemplate(self, buf):
    """_fillTemplate(buf)-->str
    Ritorna il documento con i campi sostituiti con dict_template.
    """
    try:    
        for k, v in self.dict_template.iteritems():
            if not isinstance(v,unicode):
                v=str(v)
            else:
                v=v.encode('latin-1') #In that way it works, but why?
            buf = buf.replace(k, v)

Ответы [ 3 ]

5 голосов
/ 09 марта 2012

Пока вы отвечаете на мой комментарий, вот ответ на первый вопрос:

Посмотрите на строку [7-10]. Не странно ли? Почему, если мой (строка 6) питон иметь код по умолчанию в utf-8, затем преобразовать эту строку (line7) в по-другому, что делает строка 9? Теперь взгляните на строки [11-14] и их вывод ..

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

sys.getdefaultencoding()

Это даст вам кодировку Python, используемую для реализации Unicode. Это никак не связано с выводом.

In [7]: u'è'
Out[7]: u'\xe8'
In [8]: u'è'.encode('utf8')
Out[8]: '\xc3\xa8'
In [9]: print u'è'
è
In [10]: print u'è'.encode('utf8')
è

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

Поскольку строка в юникоде не совпадает со строкой utf8, она не дает вам те же данные.

Unicode - это «нейтральное» представление строки, а utf8 - закодированное.

5 голосов
/ 09 марта 2012

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


В первом примере ваш терминал кодирует на латинице 1:

7 - >>> u'èéòç'
8 - u'\xe8\xe9\xf2\xe7'

Кодировка этих символов на латинице 1 является допустимой кодировкой тех же символов в UTF-8, поэтомуPython не нуждается ни в каком преобразовании.Когда вы переключаете свой терминал на UTF-8, вы получаете

7 - >>> u'èéòç'
8 - u'\xc3\xc3\xa8\xc3\xa9\xc3\xb2\xc3\xa7'

Ваш терминал отправляет кодировки UTF-8 в Python в виде четырех 2-байтовых последовательностей.Ваш интерпретатор Python дословно взял эти байты и сохранил их: они также являются допустимым закодированным представлением вашей строки;UTF-8 может фактически кодировать одинаковые символы несколькими способами.


Если ваш редактор сохраняет UTF-8, то вы должны поставить следующееначало вашего .py файла:

# -*- coding: utf-8 -*-

Эта строка должна соответствовать кодировке, используемой вашим редактором .


Самый надежный подход к обработке кодировок,Вероятно, один из следующих двух:

  1. Ваша программа должна манипулировать только внутренними (байтовыми) строками в кодировке single (UTF-8 - хороший выбор).Это означает, что если вы получаете, скажем, данные в кодировке Latin-1, вы должны перекодировать их в UTF-8:

    data.decode('latin1').encode('utf8')
    

    Лучший способ обработки ваших строковых литералов, в данном случае, эточтобы ваш редактор сохранил ваш файл в UTF-8 и использовал обычные (байтовые) строковые литералы ("This is a string", без u впереди).

  2. В качестве альтернативы ваша программа можетманипулировать только строками Юникода.Мой опыт показывает, что это немного громоздко с Python 2. Это был бы мой метод выбора с Python 3, хотя, поскольку Python 3 имеет гораздо более естественную поддержку для этих проблем кодирования (литеральные строки являются символьными строками, а не байтовыми строкамии т. д.).

3 голосов
/ 09 марта 2012

В строке 7 вы выводите объект Unicode:

>>> u'èéòç'
u'\xe8\xe9\xf2\xe7'

Никакого кодирования не происходит, он просто говорит, что ваш ввод состоит из единиц кода Unicode \xe8, \xe9 и так далее.

В строке 11 вы создаете строку в кодировке UTF-8 из объекта Unicode.Вывод закодированной строки выглядит иначе, чем незашифрованный объект Unicode, но почему бы и нет:

>>> u'èéòç'.encode('utf-8')
'\xc3\xa8\xc3\xa9\xc3\xb2\xc3\xa7'

Во втором эксперименте, когда вы изменили кодировку терминала, вы фактически нарушили интерпретацию входных символов:

>>> u'èéòç'
u'\xc3\xa8\xc3\xa9\xc3\xb2\xc3\xa7'

Когда вы вставляете эти четыре символа в строку, они каким-то образом кодируются, и Python думает, что вы набрали восемь байтов кода UTF-8.Но эти байты не представляют символы, которые вы хотели ввести. Похоже, Python думает, что он получит символы ISO-8859-1 из терминала, в то время как он фактически получает данные UTF-8, что приводит к путанице.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...