在 Python 裡設定 stdout 的編碼

來源:互聯網
上載者:User

有時候進程的運行環境裡,locale 會被設定成只支援 ASCII 字元集的(比如 LANG=C)。這時候 Python 就會把標準輸出和標準錯誤的編碼給設定成 ascii,造成輸出中文時報錯。

一種解決辦法是設定支援 UTF-8 的 locale,但是那需要在 Python 進程啟動前設定。啟動之後,初始化過了,再設定 locale 也不會重新初始化那些對象。

另一種辦法是往 sys.stdout.buffer 這種地方直接寫 bytes。理論上完全沒問題,但是寫起程式來好累……

我就去找了一下怎麼優雅地弄一個新的 sys.stdout 出來。Python 3 的 I/O 不再使用 C 標準庫的 I/O 函數,而是直接使用 OS 提供的介面。封裝位於 io 這個模組裡邊,有帶緩衝的,不帶緩衝的,二進位的,文本的。

研究了一下文檔可知,sys.stdout 是個 io.TextIOWrapper,有個 buffer 屬性,裡邊是個 io.BufferedWriter。我們用它造一個新的 io.TextIOWrapper,指定編碼為 UTF-8:

import sys
import io

def setup_io():
  sys.stdout = sys.__stdout__ = io.TextIOWrapper(
    sys.stdout.detach(), encoding='utf-8', line_buffering=True)
  sys.stderr = sys.__stderr__ = io.TextIOWrapper(
    sys.stderr.detach(), encoding='utf-8', line_buffering=True)
這裡除了可以設定編碼之外,也可以設定錯誤處理和緩衝。所以這個技巧也可以用來容忍編碼錯誤、改變標準輸出的緩衝(不需要在啟動的時候加 -u 了)。

其實這樣子還是不夠徹底。Python 在很多地方都有用到預設編碼。比如 subprocess,指定 universal_newlines=True 時 Python 會自動給標準輸入、輸出、錯誤編解碼,但是呢,在 Python 3.6 之前,這裡的編碼是不能手動指定的。還有參數的編碼,也是不能指定的(不過可以傳 bytes 過去)。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.