【问题标题】:How do I include unicode strings in Python doctests?如何在 Python 文档测试中包含 unicode 字符串?
【发布时间】:2009-11-14 05:51:24
【问题描述】:

我正在编写一些必须操作 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?

【问题讨论】:

    标签: python unicode doctest


    【解决方案1】:

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

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

    注意!仅将 setdefaultencoding 用于调试目的。我会接受它用于 doctest,但不会在您的生产代码中的任何地方使用。

    【讨论】:

    • 谢谢!但是,这种方法不适用于在 Python 2.x 上自动发现测试的任何包。
    【解决方案2】:

    Python 2.6.6 不能很好地理解 unicode 输出,但可以使用以下方法解决此问题:

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

    【讨论】:

      【解决方案3】:

      这似乎是 Python 中一个已知但尚未解决的问题。请参阅未解决的问题 herehere

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

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

      【讨论】:

      • 很公平,这可能是更好的通用解决方案。但是,就我而言,由于对 matplotlib 和 numpy 的依赖,我仍然受限于 Python 2.x。
      【解决方案4】:

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

      【讨论】:

      • 谢谢!不幸的是,这种方法打破了狮身人面像的'make doctest'。它最终以“utf8”编解码器无法解码位置中的字节...:无效数据。
      • 嗯。好吧,我将它用于我自己的文档测试。抱歉,我不知道这里发生了什么。
      【解决方案5】:

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

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

      要在 Python 2 中实现相同的效果,您需要保留 coding: utf-8 旁边,您可以在所有文档字符串前面加上 u 前缀,或者简单地添加

      from __future__ import unicode_literals
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-01-24
        • 1970-01-01
        相关资源
        最近更新 更多