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

Как включить строки Unicode в доктрины Python?

Я работаю над некоторым кодом, который должен управлять строками unicode. Я пытаюсь написать для него доктрины, но у меня проблемы. Ниже приведен минимальный пример, иллюстрирующий проблему:

# -*- coding: utf-8 -*-
def mylen(word):
  """
  >>> mylen(u"áéíóú")
  5
  """
  return len(word)

print mylen(u"áéíóú")

Сначала мы запускаем код, чтобы увидеть ожидаемый вывод print mylen(u"áéíóú").

$ python mylen.py
5

Далее, мы запускаем доктрину, чтобы увидеть проблему.

$ python -m
5
**********************************************************************
File "mylen.py", line 4, in mylen.mylen
Failed example:
    mylen(u"áéíóú")
Expected:
    5
Got:
    10
**********************************************************************
1 items had failures:
   1 of   1 in mylen.mylen
***Test Failed*** 1 failures.

Как я могу проверить, что mylen(u"áéíóú") оценивается до 5?

4b9b3361

Ответ 1

Если вы хотите использовать строки unicode, вы должны использовать unicode docstrings! Обратите внимание на u!

# -*- coding: utf-8 -*-
def mylen(word):
  u"""        <----- SEE 'u' HERE
  >>> mylen(u"áéíóú")
  5
  """
  return len(word)

print mylen(u"áéíóú")

Это будет работать - пока проходят тесты. Для Python 2.x вам нужен еще один взлом, чтобы сделать подробный режим доктрины или получить правильную трассировку при неудачах тестов:

if __name__ == "__main__":
    import sys
    reload(sys)
    sys.setdefaultencoding("UTF-8")
    import doctest
    doctest.testmod()

NB! Только использовать setdefaultencoding для отладки. Я бы принял его для использования доктрины, но не в любом месте вашего производственного кода.

Ответ 2

Python 2.6.6 не очень хорошо разбирается в выпуске unicode, но это можно исправить, используя:

  • уже описан хак с sys.setdefaultencoding("UTF-8")
  • unicode docstring (уже упоминалось выше, спасибо большое)
  • И print.

В моем случае эта docstring сообщает, что тест не работает:

def beatiful_units(*units):
    u'''Returns nice string like 'erg/(cm² sec)'.

    >>> beatiful_units(('erg', 1), ('cm', -2), ('sec', -1))
    u'erg/(cm² sec)'
    '''

с сообщением об ошибке

Failed example:
    beatiful_units(('erg', 1), ('cm', -2), ('sec', -1))
Expected:
    u'erg/(cm² sec)'
Got:
    u'erg/(cm\xb2 sec)'

Используя print, мы можем исправить это:

def beatiful_units(*units):
    u'''Returns nice string like 'erg/(cm² sec)'.

    >>> print beatiful_units(('erg', 1), ('cm', -2), ('sec', -1))
    erg/(cm² sec)
    '''

Ответ 3

Это похоже на известную и еще нерешенную проблему в Python. См. Открытые проблемы здесь и здесь.

Неудивительно, что он может быть изменен для работы ОК в Python 3, поскольку все строки здесь Unicode:

def mylen(word):
  """
  >>> mylen("áéíóú")
  5
  """
  return len(word)

print(mylen("áéíóú"))

Ответ 4

Мое решение состояло в том, чтобы избежать символов юникода, таких как u '\ xe1\xe9\xed\xf3\xfa'. Однако было не так легко читать, но в моих тестах было несколько символов, отличных от ASCII, поэтому в этих случаях я помещал описание в сторону как комментарий, например "# n с тильдой".

Ответ 5

Как уже упоминалось, вам нужно обеспечить, чтобы ваши docstrings были Unicode.

Если вы можете переключиться на Python 3, тогда он будет работать там автоматически, поскольку исходная кодировка уже является utf-8, а строковый тип по умолчанию - Unicode.

Чтобы достичь этого в Python 2, вам нужно сохранить coding: utf-8, рядом с которым вы можете либо префикс всех docstrings с помощью u, либо просто добавить

from __future__ import unicode_literals