2014-03-19 64 views
4

看似簡單的問題:我如何在Python3中使用print()字符串?應該是一個簡單的:如何在Python3中打印()一個字符串?

print(my_string) 

但這並不行。根據my_string,環境變量的內容和使用,將拋出一個異常UnicodeEncodeError操作系統:

>>> print("\u3423") 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
UnicodeEncodeError: 'ascii' codec can't encode character '\u3423' in position 0: ordinal not in range(128) 

有沒有解決這個乾淨的可移植的方法?

擴大一點:這裏的問題是Python3字符串包含Unicode編碼字符,而終端可以有任何編碼。如果幸運的話,您的終端可以處理字符串中包含的所有字符,並且一切都會正常,如果您的終端不能(例如有人設置LANG=C),那麼您會得到一個例外。

如果手動編碼在Python3你可以提供忽略或替換unencodable字符的錯誤處理程序的字符串:

"\u3423".encode("ascii", errors="replace") 

對於print()我沒有看到一個簡單的方法在一個錯誤處理程序,甚至堵塞如果有的話,一個普通的錯誤處理程序看起來像一個可怕的想法,因爲它會修改數據。一個條件錯誤處理程序可能會工作(即檢查isatty(),並根據該做什麼決定),但似乎非常難以通過所有的麻煩,只是print()一個字符串,我甚至不確定它不會在一些失敗案例。

一個現實世界的例子這一問題將是例如這一個:

Python3: UnicodeEncodeError only when run from crontab

+1

在Linux上適合我。您可能需要指定哪些操作系統和哪些環境變量給您帶來麻煩。 – John1024

+0

在Mac OS X上適合我,打印出一個(中文?)字符? – Nitish

+0

適用於我的Linux控制檯和X終端仿真器,但兩者都配置爲支持正確的UTF-8。我想知道,UTF-8在收到此錯誤的環境中是否能夠正常工作?也許它不僅僅是Python。 –

回答

0

解決這一問題的最實用的方法似乎爲t o強制輸出編碼爲utf-8:surrogateescape。這不僅會強制UTF-8輸出,而且還會確保可以在不拋出異常的情況下打印代理轉義字符串(由os.fsdecode()返回)。在命令行中,這看起來是這樣的:

PYTHONIOENCODING=utf-8:surrogateescape python3 -c 'print("\udcff")' 

要從程序本身有一個重新分配stdoutstderr,這是可以做到的範圍內做到這一點(的line_buffering=True是很重要的,否則輸出不會得到刷新正確):

import sys 
import io 

sys.stdout = io.TextIOWrapper(sys.stdout.buffer, errors="surrogateescape", line_buffering=True) 
sys.stderr = io.TextIOWrapper(sys.stderr.buffer, errors="surrogateescape", line_buffering=True) 

print("\udcff") 

這種做法將導致無法正確顯示在未設置爲UTF-8終端的字符,但是這對我來說似乎是強烈者優先在隨機拋出異常,並使其無法打印文件名不腐蝕它們,因爲它們可能不在任何VA中在Linux系統上完全可以編碼。

我在幾個地方看過,utf-8:surrogateescape可能會成爲未來的默認值,但從Python 3.6.0b2開始並非如此。

1

有沒有解決這個乾淨的可移植的方法?

PYTHONIOENCODING=<encoding>:<error_handler>例如,

$ PYTHONIOENCODING=utf-8 python your_script.py >output-in-utf-8.txt 

在你的情況,我想你的環境(LANGLC_CTYPE)配置爲接受非ASCII輸入:

$ locale charmap 
-1

的原因,它是給你一個錯誤是因爲它試圖破譯什麼是你。就像\ r是ASCII的回車,\ n - 換行符\ t - 標籤等等

如果:

my_string = '\u112' 
print(my_string) 

這將會給你一個錯誤,沒有它打印的 '\'試圖找出什麼\是像這樣:

my_string = '\\u122' 
print(my_string) 

輸出:

\u122