Как включить строки 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?
Ответы
Ответ 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