2009-11-14 106 views
18

我正在处理一些必须处理unicode字符串的代码。我正在为它编写doctests,但遇到了麻烦。下面是说明该问题的小例子:如何在Python doctests中包含unicode字符串?

# -*- 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?

回答

18

如果你想unicode字符串,你必须使用unicode文档字符串!注意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。我接受它用于doctest使用,但不在生产代码中的任何位置。

+0

谢谢!这种方法不适用于任何自动发现Python 2.x测试的软件包。 – saffsd 2009-11-15 22:20:31

2

这似乎是一个已知的,但尚未解决的Python问题。查看公开问题herehere

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

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

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

很公平,这可能是更好的通用解决方案。但是,就我而言,由于依赖于matplotlib和numpy,我仍然受限于Python 2.x。 – saffsd 2009-11-15 22:22:25

1

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

+0

谢谢!不幸的是,这种方法打破了狮身人面像的'make doctest'。它以'utf8'编解码器结束,无法解码位置...中的字节:无效数据。 – saffsd 2009-11-15 22:18:07

+0

嗯。那么,我将它用于我自己的文档测试。对不起,但我不知道这里发生了什么。 – 2009-11-16 01:04:58

5

的Python 2.6.6不明白Unicode的输出很好,但是这可以通过使用固定:

  • 已经描述的黑客与sys.setdefaultencoding("UTF-8")
  • 的Unicode文档字符串(上面也已经提到,非常感谢)
  • AND print声明。

在我的情况下,该文档字符串告诉测试被打破:

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) 
    ''' 
+0

最后修复'print'保存了我的一天,谢谢! – 2011-08-05 18:26:53

1

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

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

为了实现在Python 2一样,你需要保持coding: utf-8旁边,您可以前缀的所有文档字符串与u,或者简单地添加

from __future__ import unicode_literals 
相关问题