Python: увеличить специальный символ Í

Я хочу прочитать несколько слов из файла Excel и извлечь некоторую информацию. Прочитать файл не проблема.

Дело в том, что я хочу увеличить последний символ слова. Это не проблема для обычных символов, таких как «A». Но специальные символы, такие как «Í», представляют собой проблему.

Я прочитал содержание с этим:

val = val.encode('utf-8')

Я помещаю это значение в словарь.

Следующим шагом является повторение dict и получение сохраненной информации. info['streettype'] содержит мой предыдущий val. Теперь я конвертирую значение в верхний регистр следующим образом:

w2 = info['streettype'].decode('utf-8').upper().encode('utf-8')

Это необходимо, потому что некоторые символы, как я уже сказал, особенные (например, «é», «ž», «í»). Теперь я хочу увеличить последний символ слова, который может быть специальным символом.

w3 = w2.decode('utf-8')[:-1].encode('utf-8')    
lastLetter = w2.decode('utf-8')[-1].encode('utf-8')

Теперь я увеличиваю символ, используя:

lastLetter2 = (chr(ord(lastLetter.decode('utf-8')) + 1))

Далее я хочу сохранить его в текстовом файле. Я хочу сохранить исходное слово и отредактированное слово. Я думаю, что мне нужно перекодировать мой lastLetter2, но это не работает. Когда я просто сохраняю свои w2 и w3+lastLetter2, я получаю странные результаты, потому что некоторые из них закодированы, а некоторые нет.

Для слова:

NÁBŘEŽÍ

мой результат:

"NÃBŘEŽÃ", "NÃBŘEŽÎÃ"

но я хочу:

"NÁBŘEŽÍ", "NÁBŘEŽÎ"

(Í — это код ascii 205, Î — код ascii 206)

Может ли кто-нибудь помочь мне спасти эту проблему?


person oele3110    schedule 18.03.2015    source источник
comment
не оперировать (объединять, изменять символы) с закодированными строками. Работайте с юникодными (декодированными) строками и кодируйте только после того, как закончите   -  person loopbackbee    schedule 18.03.2015
comment
Í – код ascii 205, Π– код ascii 206. Нет, они не. Эти символы не входят в стандарт ASCII, в котором всего 128 кодовых точек. Это символы iso-8859-1 (Latin-1), и в этом стандарте они действительно закодированы в 205 и 206. Они также имеют один и тот же код Unicode.   -  person Martijn Pieters    schedule 18.03.2015
comment
Вы используете Python 2 или 3 здесь?   -  person Martijn Pieters    schedule 18.03.2015
comment
Я получил числа ascii отсюда ssi-developer.net/reference/ascii-0 .shtml. Я работаю на питоне 2.7   -  person oele3110    schedule 18.03.2015
comment
Почему вы хотите увеличить символ? В зависимости от кодировки вы получите совершенно разные результаты. Я не знаю о каких-либо особых отношениях между персонажами и их преемниками.   -  person André Laszlo    schedule 18.03.2015
comment
@ oele3110: эта таблица очень неправильная; вместо этого он использует кодовую страницу Windows 1252, но эта кодовая страница имеет только 256 кодовых точек. Откуда берутся оставшиеся 744 символа, никто не знает, они соответствуют Unicode, но с Windows 1252, смешанной в таблице, бесполезны. См. Википедию для правильной таблицы ASCII.   -  person Martijn Pieters    schedule 18.03.2015


Ответы (1)


Прекратите постоянно кодировать свои данные в UTF-8; сохраните свой текст в формате Unicode, это значительно упрощает обработку. Оставьте кодирование до последней минуты, желательно, чтобы файловый объект закодировал это для вас.

Наличие в файле кодировки Unicode означает, что в Python 2 вы должны использовать io.open() вместо стандартной встроенной функции open(); это та же инфраструктура, которую Python 3 использует для обработки Unicode и файлового ввода-вывода.

Вам удалось создать Mojibake, кодируя и декодируя по желанию здесь; ваш текст теперь представляет собой смесь данных UTF-8, декодированных с кодовой страницей Windows 1252, а затем снова закодированных в UTF8, плюс неискаженные данные:

>>> print u'NÃBŘEŽÃ'
NÃBŘEŽÃ
>>> print u'NÃBŘEŽÃ'[3:-1].encode('cp1252').decode('utf8')
ŘEŽ

Обратите внимание, что последний символ в первой строке недействителен; не хватает байта! Это связано с тем, что результат «декодирования» байтов UTF-8 последнего символа не должен был быть возможен в правильном кодеке CP1252; Мне пришлось использовать внутренние кодеки восстановления ftfy проекта, чтобы обойти эту проблему:

>>> print u'NÃBŘEŽÃ\x8d'[3:].encode('sloppy-cp1252').decode('utf8')
ŘEŽÍ
>>> u'Í'.encode('utf8').decode('cp1252')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/Users/mpieters/Development/venvs/stackoverflow-2.7/lib/python2.7/encodings/cp1252.py", line 15, in decode
    return codecs.charmap_decode(input,errors,decoding_table)
UnicodeDecodeError: 'charmap' codec can't decode byte 0x8d in position 1: character maps to <undefined>
>>> u'Í'.encode('utf8').decode('sloppy-cp1252')
u'\xc3\x8d'
>>> print u'Í'.encode('utf8').decode('sloppy-cp1252')
Ã

Единственный способ исправить это: а) убедиться, что вы читаете данные, используя правильные кодеки, и б) затем обрабатывать весь текст как Unicode во всем коде и кодировать только в последний момент к правильному выходному кодеку.

Обработка кодовых точек Unicode с помощью ord() и unichr() (в Python 2) и chr() в Python 3 будет работать как положено:

>>> lastletter = u'Î'
>>> ord(lastletter)
206
>>> unichr(ord(lastletter) + 1)
u'\xcf'
>>> print unichr(ord(lastletter) + 1)
Ï

Вы можете прочитать о Python и Unicode:

person Martijn Pieters    schedule 18.03.2015