(Unicode error) Кодек unicodeescape не может декодировать байты - строка с \ u - PullRequest
23 голосов
/ 29 сентября 2011

Написание своего кода для Python 2.6, но, имея в виду Python 3, я подумал, что было бы неплохо поставить

from __future__ import unicode_literals

в верхней части некоторых модулей. Другими словами, я прошу проблемы (чтобы избежать их в будущем), но я мог бы упустить некоторые важные знания здесь. Я хочу быть в состоянии передать строку, представляющую путь к файлу и создать экземпляр объекта так просто, как

MyObject('H:\unittests')

В Python 2.6 это работает просто отлично, не нужно использовать двойную обратную косую черту или необработанную строку, даже для каталога, начинающегося с '\u..', что именно то, что я хочу. В методе __init__ я проверяю, что все одиночные \ вхождения интерпретируются как '\\', включая те, что перед специальными символами, как в \a, \b, \f, \n, \r , \t и \v (только \x остается проблемой). Также декодирование данной строки в Unicode с использованием (локального) кодирования работает, как и ожидалось.

Подготовка к Python 3.x , моделирующая мою реальную проблему в редакторе (начиная с чистой консоли в Python 2.6), происходит следующее:

>>> '\u'
'\\u'
>>> r'\u'
'\\u'

(ОК, пока здесь: '\u' кодируется консолью с использованием локальной кодировки)

>>> from __future__ import unicode_literals
>>> '\u'
SyntaxError: (unicode error) 'unicodeescape' codec can't decode bytes in position 0-1: end of string in escape sequence

Другими словами, строка (Unicode) вообще не интерпретируется как Unicode, и при этом она не декодируется автоматически с локальной кодировкой. Даже для сырой строки:

>>> r'\u'
SyntaxError: (unicode error) 'rawunicodeescape' codec can't decode bytes in position 0-1: truncated \uXXXX

то же самое для u'\u':

>>> u'\u'
SyntaxError: (unicode error) 'unicodeescape' codec can't decode bytes in position 0-1: end of string in escape sequence

Кроме того, я ожидаю, что isinstance(str(''), unicode) вернет True (чего не происходит), потому что импорт unicode_literals должен сделать все строковые типы Unicode. (edit:) Поскольку в Python 3, все строки являются последовательностями символов Unicode , я ожидал бы, что str('')) вернет такую ​​строку Unicode, а type(str('')) будет одновременно <type 'unicode'> и <type 'str'> (потому что все строки в Unicode), но также понимают, что <type 'unicode'> is not <type 'str'>. Беспорядок вокруг ...

Вопросы

  • как мне лучше всего передать строки, содержащие '\u'? (без записи '\\u')
  • действительно ли from __future__ import unicode_literals реализует все связанные с Python 3. изменения юникода, так что я получаю полную строковую среду Python 3?

редактирование: В Python 3 <type 'str'> является объектом Unicode , а <type 'unicode'> просто не существует. В моем случае я хочу написать код для Python 2 (.6), который будет работать в Python 3. Но когда я import unicode_literals, я не могу проверить, имеет ли строка значение <type 'unicode'>, потому что:

  • Я полагаю, unicode не является частью пространства имен
  • , если unicode является частью пространства имен, литерал <type 'str'> по-прежнему в кодировке Unicode при создании в том же модуле
  • type(mystring) всегда будет возвращать <type 'str'> для литералов Unicode в Python 3

Мои модули используются для кодирования в 'utf-8' комментарием # coding: UTF-8 вверху, а мой locale.getdefaultlocale()[1] возвращает 'cp1252'. Поэтому, если я вызываю MyObject('çça') из моей консоли, он кодируется как 'cp1252' в Python 2 и в 'utf-8' при вызове MyObject('çça') из модуля. В Python 3 он не будет закодирован, но будет литералом Unicode.

редактирование:

Я потерял надежду на то, что мне будет позволено избегать использования '\' до u (или x в этом отношении). Также я понимаю ограничения импорта unicode_literals. Однако из-за множества возможных комбинаций передачи строки из модуля в консоль и наоборот с каждой другой кодировкой, а также при импорте unicode_literals или нет и Python 2 против Python 3, я захотел создать обзор путем актуальное тестирование. Отсюда и таблица ниже. enter image description here

Другими словами, type(str('')) не возвращает <type 'str'> в Python 3, но <class 'str'>, и все проблемы Python 2, похоже, избегаются.

Ответы [ 4 ]

17 голосов
/ 29 сентября 2011

AFAIK, все, что from __future__ import unicode_literals делает, это делает все строковые литералы типа юникода, а не типа строки. То есть:

>>> type('')
<type 'str'>
>>> from __future__ import unicode_literals
>>> type('')
<type 'unicode'>

Но str и unicode - все еще разные типы, и они ведут себя так же, как и раньше.

>>> type(str(''))
<type 'str'>

Всегда имеет тип str.

Что касается вашей r'\u' проблемы, она задуманна, поскольку эквивалентна ru '\ u' без unicode_literals. Из документов:

Когда префикс 'r' или 'R' используется вместе с префиксом 'u' или 'U', тогда escape-последовательности \ uXXXX и \ UXXXXXXXX обрабатываются, а все другие обратные слэши остаются в строке.

Вероятно, из-за работы лексического анализатора в серии python2. В python3 это работает так, как вы (и я) ожидали.

Вы можете ввести обратную косую черту дважды, и тогда \u не будет интерпретироваться, но вы получите две обратной косой черты!

Обратная косая черта может быть экранирована предыдущей обратной косой чертой; однако оба остаются в строке

>>> ur'\\u'
u'\\\\u'

Итак, ИМХО, у вас есть два простых варианта:

  • Не используйте необработанные строки и избегайте обратной косой черты (совместимо с python3):

    'H:\\unittests'

  • Будьте слишком умны и пользуйтесь кодовыми точками Юникода ( не совместим с python3):

    r'H:\u005cunittests'

0 голосов
/ 02 ноября 2017

Я пытаюсь это сделать на Python 3:

import os

os.path.abspath ("yourPath")

и все работает!

0 голосов
/ 12 февраля 2017

Для меня этот вопрос связан с версией не обновленной, в данном случае numpy

Исправить:

conda install -f numpy
0 голосов
/ 29 сентября 2011

Когда вы пишете строковые литералы, которые содержат обратную косую черту, например пути (в Windows) или регулярные выражения, используйте необработанные строки.Вот для чего они.

...