私はすべてのロケールがUTF-8である最近のLinuxシステムを実行しています。
LANG=de_DE.UTF-8
LANGUAGE=
LC_CTYPE="de_DE.UTF-8"
LC_NUMERIC="de_DE.UTF-8"
LC_TIME="de_DE.UTF-8"
...
LC_IDENTIFICATION="de_DE.UTF-8"
LC_ALL=
次に、UTF-8でエンコードされたコンテンツをコンソールに書き込みたいと思います。
現在、PythonはFSエンコーディングにUTF-8を使用していますが、デフォルトのエンコーディングにはASCIIを使用しています:
>>> import sys
>>> sys.getdefaultencoding()
'ascii'
>>> sys.getfilesystemencoding()
'UTF-8'
これを行うための最良の(クリーンな)方法は、PYTHONIOENCODING
環境変数を設定することだと思いました。しかし、Pythonはそれを無視しているようです。少なくとも私のシステムでは、envvarを設定した後でも、デフォルトのエンコーディングとしてascii
を取得し続けます。
# tried this in ~/.bashrc and ~/.profile (also sourced them)
# and on the commandline before running python
export PYTHONIOENCODING=UTF-8
スクリプトの開始時に次の操作を行うと、機能します。
>>> import sys
>>> reload(sys) # to enable `setdefaultencoding` again
<module 'sys' (built-in)>
>>> sys.setdefaultencoding("UTF-8")
>>> sys.getdefaultencoding()
'UTF-8'
しかし、そのアプローチは汚れているようです。それで、これを達成する良い方法は何ですか?
デフォルトのエンコーディングを変更する代わりに-良いアイデアではありません(メジリアックの答えを参照)-sys.stdout
でStreamWriter
このような:
sys.stdout = codecs.getwriter(locale.getpreferredencoding())(sys.stdout)
それを処理する小さなユーティリティ関数については---(this Gist を参照してください。
UTF-8でエンコードされたテキストをコンソールにPython <3?
print u"some unicode text \N{EURO SIGN}"
print b"some utf-8 encoded bytestring \xe2\x82\xac".decode('utf-8')
つまり、Unicode文字列がある場合は、直接印刷します。バイト文字列がある場合は、最初にUnicodeに変換します。
ロケール設定(LANG
、LC_CTYPE
)はutf-8ロケールを示しているため、理論的にはutf-8バイト文字列を直接印刷でき、ターミナルに正しく表示されるはずです(ターミナル設定がロケール設定である必要があります)、それを避ける必要があります:スクリプト内の環境の文字エンコーディングをハードコードしないでください; 代わりにUnicodeを直接印刷します。
あなたの質問には多くの間違った仮定があります。
Unicodeを端末に出力するために、ロケール設定でPYTHONIOENCODING
を設定する必要はありません。 utf-8ロケールはすべてのUnicode文字をサポートします。つまり、そのまま動作します。
回避策sys.stdout = codecs.getwriter(locale.getpreferredencoding())(sys.stdout)
は必要ありません。一部のコード(制御しない)がバイトを印刷する必要がある場合、および/または nicodeをWindowsコンソールに印刷する(誤ったコードページ、デコードできない文字を印刷できない) の場合、破損する可能性があります。正しいロケール設定および/またはPYTHONIOENCODING
envvarで十分です。また、sys.stdout
を置き換える必要がある場合は、 codecs
モジュールの代わりにio.TextIOWrapper()
を使用してくださいwin-unicode-console
package と同様です。
sys.getdefaultencoding()
は、ロケール設定およびPYTHONIOENCODING
とは無関係です。 PYTHONIOENCODING
の設定がsys.getdefaultencoding()
を変更するという仮定は誤りです。代わりにsys.stdout.encoding
を確認する必要があります。
コンソールに印刷する場合、sys.getdefaultencoding()
は使用されません。 PYTHOHIOENCODING
が設定されていない限り、stdoutがファイル/パイプにリダイレクトされる場合、Python 2のフォールバックとして使用できます。
$ python2 -c'import sys; print(sys.stdout.encoding)'
UTF-8
$ python2 -c'import sys; print(sys.stdout.encoding)' | cat
None
$ PYTHONIOENCODING=utf8 python2 -c'import sys; print(sys.stdout.encoding)' | cat
utf8
sys.setdefaultencoding("UTF-8")
;を呼び出さないでください。データが破損する可能性があります黙っておよび/または予期しないサードパーティのモジュールが破損する可能性があります。 sys.getdefaultencoding()
は、バイト文字列(str
)とunicode
in Python 2 暗黙的にたとえば"a" + u"b"
との間の変換に使用されます。また、 @ mesilliacの答えの引用 。
これを達成することは推奨されません。
Fedoraは システムロケールをデフォルトとして使用 を提案しましたが、明らかにこれは他のことを壊します。
メーリングリストの議論 からの引用です:
Pythonでサポートされているデフォルトのエンコーディングは、 Python 2.x:ASCII Python 3.x:UTF-8 これらを変更すると、あなたは自分自身であり、奇妙なことが 開始しますデフォルトのエンコーディングは、 Pythonと外界との間の変換だけでなく、 8ビット文字列とUnicode間のすべての内部変換にも影響します。 。 pangoモジュールで行われていることのようにハックします( を取得するためにサイトモジュールを sys.setdefaultencoding()API back)はまさに まったく間違っており、Unicode オブジェクトがデフォルトのエンコードされた表現をキャッシュするため、深刻な問題を引き起こします。 しないでくださいロケールベースのデフォルトエンコーディングの使用を有効にします。 達成したいのが、 stdoutおよびstdinのエンコーディングをパイプ用に正しく設定することだけなら、 instこれらの(のみ)の.encoding属性を変更します。 - Marc-Andre Lemburg eGenix.com
これは私がそれを行う方法です:
#!/usr/bin/python2.7 -S
import sys
sys.setdefaultencoding("utf-8")
import site
Banglineの-S
に注意してください。これは、Python=自動的にsite
モジュールをインポートしないようにします。site
モジュールは、デフォルトのエンコードを設定し、メソッドを削除して、ただし、既に設定されているものは尊重されます。
プログラムが画面に適切な文字、つまり無効なシンボルを表示しない場合、次のコマンドラインでプログラムを実行します。
PYTHONIOENCODING=utf8 python3 yourprogram.py
または、プログラムがグローバルにインストールされたモジュールの場合、次のようになります。
PYTHONIOENCODING=utf8 yourprogram
一部のプラットフォームでは、Cygwin(mintty.exe
ターミナル)Anaconda Python
(またはPython 3
)、単にexport PYTHONIOENCODING=utf8
以降、プログラムを実行しても動作しません。常に毎回実行する必要がありますPYTHONIOENCODING=utf8 yourprogram
プログラムを正しく実行します。
Linuxでは、Sudo
の場合、-E
引数を使用して、ユーザー変数をSudoプロセスにエクスポートします。
export PYTHONIOENCODING=utf8
Sudo -E python yourprogram.py
これを試してもうまくいかなかった場合は、Sudo Shellを起動する必要があります。
Sudo /bin/bash
PYTHONIOENCODING=utf8 yourprogram
関連する: