Как правильно работать с символами юникода в python, чтобы избежать ошибок? - PullRequest
2 голосов
/ 10 февраля 2010

Я работаю над плагином Python для окна быстрого поиска Google, и он делает некоторые странные вещи с не-ascii символами. Кажется, что код работает нормально до тех пор, пока я не попытаюсь создать строку, содержащую не-ascii символы (ü был моим тестовым символом). Я использую следующий фрагмент кода для конструкции с new_task в качестве переменной, которая вводится из GQSB.

the_sig = ("%sapi_key%sauth_token%smethod%sname%sparse%stimeline%s" %
           (api_secret, api_key, the_token, method, new_task, doParse, timeline))

Это дает мне эту ошибку:

UnicodeDecodeError: кодек «ascii» не может декодировать байт 0xc3 в позиции 0: порядковый номер не в диапазоне (128)

Я правильно понимаю, это потому, что я пытаюсь связать воедино символ Юникода внутри строки ascii. Все, что я мог найти, подсказало мне объявить кодировку сверху с помощью:

# -*- coding: iso-8859-15 -*-

Что у меня есть. И когда я извлекаю фрагмент кода, который создает строку в новый скрипт, он работает просто отлично. Но по какой-то причине, в контексте остальной части кода, каждый раз происходит сбой. Единственное, о чем я могу думать, это о том, что он внутри своего класса, но для меня это не имеет никакого смысла.

Полный код можно найти на GitHub здесь

Заранее спасибо за любую помощь. Я поставлен в тупик на этом.

Ответы [ 3 ]

4 голосов
/ 10 февраля 2010

Есть несколько вещей, которые вы должны сделать, чтобы это исправить.

  1. Преобразование всех строковых литералов, содержащих не-ASCII-символы, в литералы Юникода. Пример: u'über'.

  2. Выполнить промежуточную обработку на Unicode. Другими словами, если вы получаете закодированную строку (независимо от кодировки), перед работой с ней декодируйте ее в Unicode. Пример:

    s = utf8_string.decode('utf8') + latin1_string.decode('latin1')
    
  3. При выводе строки или ее отправке куда-нибудь закодируйте ее с помощью кодировки, понятной вашему получателю. Пример: send(s.encode('utf8')).

Полный пример:

input1 = get_possibly_nonascii_input().decode('iso-8859-1')
input2 = get_possibly_nonascii_input().decode('iso-8859-1')
input3 = u'üvw'

s =  u'%s -> %s' % (input3, (input1 + input2).upper())

send_output(s.encode('utf8'))
1 голос
/ 10 февраля 2010

Полагаю, вы используете Python 2.x.

Объявление кодировки файла определяет, как строка литералы читаются интерпретатором.

Вы должны обрабатывать все строки как unicode значения, а не str. Если вы читаете str из внешнего мира, вы должны явно расшифровать его до unicode. То же самое относится к выводу строк.

# -*- coding: utf-8 -*-
u_dia_str = '\xc3\xbc'   # str
lambda_unicode = u'λ'    # unicode

# input value
u_dia = u_dia_str.decode('utf-8')

sig_unicode = u'%s%s' % (u_dia, lambda_unicode)
# => u'üλ'

# output value
sig_str = sig_unicode.encode('utf-8')
# => '\xc3\xbc\xce\xbb'
0 голосов
/ 10 февраля 2010

Это немного вне моей компетенции, но я думаю, что # -*- coding: iso-8859-15 -*- вверху объявляет кодировку текста, в которой сохранен ваш исходный файл Python.

Действительно ли оно сохранено в ISO-8859-15?

...