Подтвердить что ты не робот

Есть ли простой способ сделать работу юникода в python?

Я пытаюсь разобраться с unicode в python 2.7.2. Я знаю, что есть .encode('utf-8') вещь, но 1/2 времени, когда я добавляю ее, я получаю ошибки, и 1/2, когда я не добавляю ее, я получаю ошибки.

Есть ли способ рассказать python - что я думал, был современным и современным языком, чтобы просто использовать unicode для строк, а не заставлять меня перемещаться с помощью материалов .encode('utf-8')?

Я знаю... python 3.0 должен это делать, но я не могу использовать 3.0 и 2.7, все равно не все так...

Например:

url = "http://en.wikipedia.org//w/api.php?action=query&list=search&format=json&srlimit=" + str(items) + "&srsearch=" + urllib2.quote(title.encode('utf-8'))
UnicodeDecodeError: 'ascii' codec can't decode byte 0xc3 in position 19: ordinal not in range(128)

Обновление Если я удалю все мои инструкции .encode из всего моего кода и добавлю # -*- coding: utf-8 -*- в начало моего файла, прямо под #!/usr/bin/python, тогда я получу следующее, как если бы я не добавил # -*- coding: utf-8 -*- в все.

/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/urllib.py:1250: UnicodeWarning: Unicode equal comparison failed to convert both arguments to Unicode - interpreting them as being unequal
  return ''.join(map(quoter, s))
Traceback (most recent call last):
  File "classes.py", line 583, in <module>
    wiki.getPage(title)
  File "classes.py", line 146, in getPage
    url = "http://en.wikipedia.org/w/api.php?action=query&prop=revisions&format=json&rvprop=content&rvlimit=1&titles=" + urllib2.quote(title)
  File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/urllib.py", line 1250, in quote
    return ''.join(map(quoter, s))
KeyError: u'\xf1'

Я не вручную набираю строку, я разбираю HTML и json с веб-сайтов. Таким образом, скрипты/bytestreams/независимо от того, что они есть, созданы python.

Обновление 2. Я могу перемещать ошибку, но она просто продолжает появляться в новых местах. Я надеялся, что python станет полезным инструментом для написания сценариев, но, похоже, через 3 дня не повезло, я просто попробую другой язык. Его позор, python предварительно установлен на osx. Я отметил правильный ответ, который зафиксировал один экземпляр ошибки, которую я опубликовал.

4b9b3361

Ответ 1

Невозможно сделать unicode "просто работать", кроме использования строк Unicode, и сразу же декодировать любую закодированную строку, которую вы получаете. Проблема в том, что вы ДОЛЖНЫ ВСЕГДА держать прямо, имеете ли вы дело с закодированными или незарегистрированными данными или используете инструменты, которые отслеживают это для вас, или у вас будет плохое время.

Python 2 делает некоторые вещи, которые являются проблематичными для этого: он делает str "по умолчанию", а не unicode для таких вещей, как строковые литералы, он молча приравнивает str к unicode при добавлении двух, и он позволяет вам вызывать .encode() в уже закодированной строке для двойного кодирования. В результате существует множество кодировщиков python и библиотек python, которые не имеют представления о том, какие кодировки они предназначены для работы, но тем не менее предназначены для работы с определенной кодировкой, поскольку тип str предназначен для программист сам управляет кодировкой. И вы должны думать о кодировке каждый раз, когда вы используете эти библиотеки, поскольку они не поддерживают тип unicode.


В вашем конкретном случае первая ошибка говорит вам, что вы имеете дело с закодированными данными UTF-8 и пытаетесь их дважды закодировать, тогда как 2-й говорит вам, что вы имеете дело с данными UNencoded. Похоже, что у вас могут быть оба. Вы действительно должны найти и исправить источник проблемы (я подозреваю, что это связано с молчаливым принуждением, о котором я упоминал выше), но вот хак, который должен исправить его в ближайшей перспективе:

encoded_title = title
if isinstance(encoded_title, unicode):
    encoded_title = title.encode('utf-8')

Если это на самом деле случай молчаливого принуждения, кусающего вас, вы должны иметь возможность легко отслеживать проблему, используя отличный unicode-nazi:

python -Werror -municodenazi myprog.py

Это даст вам трассировку прямо в точке unicode, протекающей в ваши строки, отличные от юникода, вместо того, чтобы пытаться устранить этот исключающий путь по пути от реальной проблемы. Подробнее см. Мой ответ на этот вопрос.

Ответ 2

Это очень старый вопрос, но просто хотел добавить одно частичное предложение. В то время как я сочувствую болью ОП - пережив это много, - вот один (частичный) ответ, чтобы сделать вещи "проще". Поместите это в начало любого Python 2.7 script:

from __future__ import unicode_literals

Это, по крайней мере, гарантирует, что ваши собственные литералы по умолчанию будут использовать unicode, а не str.

Ответ 3

Да, укажите данные в формате Юникода как литералы в формате Юникод:

>>> u'Hi, this is unicode: üæ'
u'Hi, this is unicode: üæ'

Обычно вы хотите использовать escape-последовательности\\ uuxxxx\unicode или задавать кодировку исходного кода. Например, следующая строка в верхней части вашего модуля устанавливает кодировку в UTF-8:

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

Прочитайте Python Unicode HOWTO для получения подробной информации, такой как кодировки по умолчанию и т.д. (кодировка исходного кода по умолчанию, например, ASCII).

Что касается вашего конкретного примера, ваш заголовок не является литералом Unicode, а строкой байта python, и python пытается его декодировать в unicode для вас, чтобы вы могли снова закодировать его. Это не удается, поскольку кодек по умолчанию для таких автоматических кодировок - ASCII:

>>> 'å'.encode('utf-8')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
UnicodeDecodeError: 'ascii' codec can't decode byte 0xc3 in position 0: ordinal not in range(128)

Кодировка применяется только к фактическим строкам Unicode, поэтому строка байта должна быть явно расшифрована:

>>> 'å'.decode('utf-8').encode('utf-8')
'\xc3\xa5'

Если вы привыкли к Python 3, то литералы Unicode в Python 2 (u'') - это новый тип строки по умолчанию в Python 3, а регулярные (байтовые) строки в Python 2 ('') такие же, как bytes объектов в Python 3 (b'').

Если у вас есть ошибки как с вызовом кодирования, так и без него на title, у вас есть смешанные данные. Проверьте заголовок и закодируйте по мере необходимости:

if isinstance(title, unicode):
    title = title.encode('utf-8')

Возможно, вам захочется узнать, что создает смешанные заголовки в формате unicode/byte, и исправить этот источник, чтобы всегда создавать тот или иной файл.

Ответ 4

убедитесь, что заголовок в вашем title.encode( "utf-8" ) является типом unicode и не использует str ( "İŞşĞğÖöÜü" )

используйте unicode ( "ĞğıIİiÖöŞşcçÇ" ) в ваших строковедах

Ответ 5

На самом деле, самый простой способ заставить Python работать с unicode - использовать Python 3, где по умолчанию используется unicode.

К сожалению, для P3 написано не так много библиотек, а также некоторые основные различия в кодировании и использовании ключевых слов. Что проблема у меня: библиотеки, которые мне нужны, доступны только для P 2.7, и я не знаю достаточно, чтобы преобразовать их в P 3.: (