2009-11-14 34 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 
相關問題