簡體   English   中英

Python3 utf-8解碼問題

[英]Python3 utf-8 decode issue

以下代碼在我的Windows機器上使用Python3運行正常並打印字符'é':

data = b"\xc3\xa9"

print(data.decode('utf-8'))

但是,在基於Ubuntu的docker容器上運行相同會導致:

UnicodeEncodeError: 'ascii' codec can't encode character '\xe9' in position 0: ordinal not in range(128)

有什么必須安裝才能啟用utf-8解碼嗎?

問題在於print()表達式,而不是decode()方法。 如果你仔細一看,出現的異常是Unicode codeError,而不是一個- codeError。

每當你使用print()函數時,Python都會將其參數轉換為str ,然后將結果編碼為bytes ,這些bytes將被發送到終端(或運行的任何Python)。 用於編碼的編解碼器(例如UTF-8或ASCII)取決於環境。 在一個理想的情況下,

  • Python使用的編解碼器與終端所期望的編解碼器兼容,因此字符顯示正確(否則你會得到像“é”而不是“é”的mojibake);
  • 使用的編解碼器涵蓋了一系列足以滿足您需求的字符(例如UTF-8或UTF-16,它們包含所有字符)。

在您的情況下,您提到的Linux docker不符合第二個條件:使用的編碼是ASCII,它只支持舊英文打字機上的字符。 這些是解決此問題的幾個選項:

  • 設置環境變量:在Linux上,Python的編碼默認值取決於此(至少部分)。 根據我的經驗,這是一個試驗和錯誤; LC_ALL設置為包含“UTF-8”的東西曾經為我工作過一次。 您必須將它們放在終端運行的shell的啟動腳本中,例如。 .bashrc
  • 重新編碼STDOUT,如下所示:

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

    使用的編碼必須匹配終端之一。

  • 自己編碼字符串並將它們發送到sys.stdout底層的二進制緩沖區,例如。 sys.stdout.buffer.write("é".encode('utf8')) 這當然是比print("é")更多的樣板。 同樣,使用的編碼必須匹配終端之一。
  • 完全避免print() 使用open(fn, encoding=...)作為輸出,進度信息的日志記錄模塊 - 取決於腳本的交互方式,這可能是值得的(誠然,在寫入STDERR時可能會遇到相同的編碼問題)記錄模塊)。

可能還有其他選擇,但我懷疑有更好的選擇。

似乎ubuntu - 取決於版本 - 使用一個或另一個編碼作為默認值,它也可能在shell和python之間有所不同。 通過這個帖子這個博客

因此推薦的方法似乎是告訴你的python實例使用utf-8作為默認編碼:

通過環境變量設置python源文件的默認編碼:

export PYTHONIOENCODING=utf8

此外,在源文件中,您可以聲明您希望顯式使用的編碼,因此無論環境設置如何,它都應該工作(請參閱此問題+答案python文檔PEP 263

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
....

關於python讀取的文件編碼的解釋,您可以在open命令中明確指定它

with open(fname, "rt", encoding="utf-8") as f:
    ...

並且有一些更具有一些副作用的hackish方式,但是每次都會保存你以明確指定它

import sys
# sys.setdefaultencoding() does not exist, here!
reload(sys)  # Reload does the trick!
sys.setdefaultencoding('UTF8')

請在相關的答案和評論中閱讀有關此黑客的警告。

暫無
暫無

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

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