如何在Python doctests中包含unicode字符串?

时间:2009-11-14 05:51:24

标签: python unicode doctest

我正在研究一些必须操纵unicode字符串的代码。我正在尝试为它编写doctests,但我遇到了麻烦。以下是说明问题的最小示例:

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

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

首先,我们运行代码以查看print mylen(u"áéíóú")的预期输出。

$ python mylen.py
5

接下来,我们运行doctest来查看问题。

$ 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?

5 个答案:

答案 0 :(得分:19)

如果你想要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,您需要另一个hack来使详细的doctest模式工作或在测试失败时获得正确的回溯:

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

NB!只能使用setdefaultencoding进行调试。我接受它用于doctest,但不能在生产代码中的任何地方接受。

答案 1 :(得分:6)

Python 2.6.6不能很好地理解unicode输出,但可以使用以下方法修复:

  • 已经用sys.setdefaultencoding("UTF-8")
  • 描述了hack
  • unicode docstring(上面已经提到过,非常感谢)
  • AND 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)
    '''

答案 2 :(得分:2)

这似乎是Python中一个已知且尚未解决的问题。查看未解决的问题herehere

毫不奇怪,它可以修改为在Python 3中正常工作,因为所有字符串都是Unicode:

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

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

答案 3 :(得分:1)

我的解决方案是逃避unicode字符,例如你'\ xe1 \ xe9 \ xed \ xf3 \ xfa'。虽然不是那么容易阅读,但我的测试只有一些非ASCII字符,所以在这些情况下我把描述放在一边作为注释,比如“#n with tilde”。

答案 4 :(得分:1)

如前所述,您需要确保您的文档字符串是Unicode。

如果你可以切换到Python 3,那么它会在那里自动工作,因为两者源编码已经是utf-8而默认的字符串类型是Unicode。

要在Python 2中实现相同功能,您需要保留旁边的coding: utf-8,您可以使用u为所有文档字符串添加前缀,或者只需添加

from __future__ import unicode_literals