簡體   English   中英

小寫時python3 unicode失敗

[英]python3 unicode fails when lowercasing

我面對的是Python 3的一個非常奇怪的問題:

>>> a = "abcé"
>>> a
'abcé'
>>> print(a)
abcé
>>> print(a.lower())
abc�

我不知道這是從哪里來的,但是它無法將小寫的unicode字符小寫。 請注意,我無法在任何地方重現該錯誤,這只是在我的一台計算機上,我遇到以下問題。 另外,同一台計算機上的python2可以正確打印abcé

另外, a.upper()返回ABCé而不是ABCÉ ,因此它不會遇到比lower ..相同的問題。

有任何想法嗎?

我不完全確定這里會發生什么,但是看起來好像是python和您的終端之間的一些編碼問題。

無論如何,最佳實踐是將所有內容都保留在'utf-8'中,以確保您可以從python內部import localelocale.setlocale(locale.LC_ALL, 'en_US.UTF-8')export LC_ALL=en_US.utf8

我不是100%熟練使用這些編碼主題,因此也許編碼專家可以提供更好的答案/解釋,但這應該可以解決您的情況。

您觀察到的行為確實非常奇特:字母“é”不受Python的str.upper() ,而由str.lower()轉換為替換字符。 同樣奇怪的是,這似乎取決於環境,因為上述str方法沒有任何本地化(即使有時可以說是有意義的,例如土耳其語“ i”→“İ”映射的情況)和“ı”→“ I”),但始終使用Unicode的默認大小寫算法。

可能的解釋

對於這種奇怪現象的最可能的解釋是,Python無法“看到”與您相同的數據。 就像Hansaplast在他們的回答中所寫的那樣,終端和Python解釋器之間可能存在編碼不匹配的情況。 通常不必關心這一點,但是當您使用交互式解釋器時,顯示鍵入和打印字符的工作實際上不是由Python執行的,而是由終端[模擬器]執行的,而這一額外的層可以是有時問題的根源。

那么到底是怎么回事? 我相信以下情況可以解釋觀察到的行為:

  • 您的終端配置為使用UTF-8。 當您鍵入“é”時,它將把字節C3 A9發送給Python。 當它從Python接收C3 A9時,將顯示“é”。
  • 但是,通過locale.getlocale()的返回值可以確認,Python使用Latin-1。 當它收到C3 A9 ,會將其解碼為“Ô,這是mojibake的常見情況。
  • UTF-8和Latin-1都是ASCII的超集,因此,只要您僅使用ASCII字符,就不會出現這種配置錯誤。 當您鍵入“ A”時,Python讀取“ A”,並且輸出相同。

關於這種錯誤配置的真正討厭的事情是它僅在某些情況下可見。 由於編碼/解碼的對稱性,即使是非ASCII字符也可能會被忽略。 如果Python只是回顯其輸入,即。 打印“Ô,這將由終端解映射為“é”,因此隱藏了錯誤。 但是,當以某種方式(例如str.upper()lower()解釋各個字符時,可能會發生意外情況。

在您的情況下, .upper()不起作用,因為“Ô已經是大寫字母,而“©”則沒有大小寫。 這就是為什么'abcé'.upper()在屏幕上顯示'ABCé'的原因。 但是小寫會產生“ã©”,Python將其編碼為E3 A9 由於這不是有效的UTF-8字節序列,因此終端無法解釋它並顯示替換字符( )。

解決方案

如果這個解釋正確,那么如何解決編碼錯誤配置?

  • 對於交互式會話,Python使用諸如LC_ALL環境變量來設置STDIN / STDOUT的編碼可能是有意義的。 在您的終端中運行的shell的啟動腳本中,添加諸如export LC_ALL=en_US.utf8類的行。 .bashrc 從Python內部更改語言環境無效,因為STD流編碼是在啟動時設置的,並且在調用locale.selocale()時不會更新。

  • 對於腳本,您可能不想依賴環境變量。 您可以圍繞每個標准通道下面的二進制流創建一個新的io.TextIOWrapper

     sys.stdin = open(sys.stdin.buffer.fileno(), encoding='utf8') sys.stdout = open(sys.stdout.buffer.fileno(), 'w', encoding='utf8') sys.stderr = open(sys.stderr.buffer.fileno(), 'w', encoding='utf8') 

    (我不建議在交互式會話中使用此解決方案。尤其是如果您輸錯了某些內容,則可能會遇到難以恢復的情況。)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM