これをスクリプトの上部で使用するpyスクリプトはほとんど見ていません。どのような場合に使用する必要がありますか?
import sys
reload(sys)
sys.setdefaultencoding("utf-8")
ドキュメントに従って:これにより、デフォルトのASCIIからUTF-8などの他のエンコーディングに切り替えることができます。UTF-8は、Pythonランタイムが文字列バッファーをユニコード。
この関数は、Pythonが環境をスキャンするとき、Python起動時にのみ使用できます。システム全体のモジュールsitecustomize.py
で呼び出す必要があります。このモジュールが評価された後、setdefaultencoding()
関数はsys
モジュールから削除されます。
実際に使用する唯一の方法は、属性を戻すリロードハックを使用することです。
また、sys.setdefaultencoding()
の使用は常に推奨されておらず、py3kではノーオペレーションになっています。 py3kのエンコーディングは「utf-8」に固定されており、変更するとエラーが発生します。
私は読むためのいくつかの指針を提案します:
答えはNEVER! (あなたが何をしているのかを本当に知っていない限り)
エンコード/デコードを適切に理解することで、9/10倍のソリューションを解決できます。
1/10人のロケールまたは環境が誤って定義されており、以下を設定する必要があります。
PYTHONIOENCODING="UTF-8"
コンソール印刷の問題を修正するための環境で。
(再使用を避けるために取り消し線で)Python 2.xがUnicode()をstr()に変換する必要があるとき(およびその逆)に使用されるデフォルトのエンコード/デコードを変更します。与えられた。つまり:sys.setdefaultencoding("utf-8")
str(u"\u20AC")
unicode("€")
"{}".format(u"\u20AC")
Python 2.xでは、デフォルトのエンコーディングはASCIIに設定されており、上記の例は次のように失敗します。
UnicodeDecodeError: 'ascii' codec can't decode byte 0xe2 in position 0: ordinal not in range(128)
(私のコンソールはUTF-8として構成されているため、"€" = '\xe2\x82\xac'
、したがって\xe2
の例外)
または
UnicodeEncodeError: 'ascii' codec can't encode character u'\u20ac' in position 0: ordinal not in range(128)
これらはmeで機能しますが、UTF-8を使用していない人には必ずしも機能しません。 ASCIIのデフォルトは、エンコードの前提がコードに焼き付けられないことを保証しますsys.setdefaultencoding("utf-8")
また、コンソールに文字を出力するときに使用されるsys.setdefaultencoding("utf-8")
sys.stdout.encoding
を修正するように見えるという副作用もあります。 Pythonは、ユーザーのロケール(Linux/OS X/Un * x)またはコードページ(Windows)を使用してこれを設定します。時々、ユーザーのロケールが壊れていて、console encodingを修正するためにPYTHONIOENCODING
が必要なだけです。
例:
$ export LANG=en_GB.gibberish
$ python
>>> import sys
>>> sys.stdout.encoding
'ANSI_X3.4-1968'
>>> print u"\u20AC"
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
UnicodeEncodeError: 'ascii' codec can't encode character u'\u20ac' in position 0: ordinal not in range(128)
>>> exit()
$ PYTHONIOENCODING=UTF-8 python
>>> import sys
>>> sys.stdout.encoding
'UTF-8'
>>> print u"\u20AC"
€
デフォルトのエンコードはASCIIであるとの理解のもと、人々はPython 2.xに対して16年間開発を続けてきました。 UnicodeError
例外処理メソッドは、非ASCIIを含むことが判明した文字列の文字列からUnicodeへの変換を処理するために記述されています。
から https://anonbadger.wordpress.com/2015/06/16/why-sys-setdefaultencoding-will-break-code/
def welcome_message(byte_string):
try:
return u"%s runs your business" % byte_string
except UnicodeError:
return u"%s runs your business" % unicode(byte_string,
encoding=detect_encoding(byte_string))
print(welcome_message(u"Angstrom (Å®)".encode("latin-1"))
Defaultencodingを設定する前は、このコードはASCIIエンコードの「Å」をデコードできず、例外ハンドラーを入力してエンコードを推測し、適切にUnicodeに変換していました。印刷:Angstrom(Å®)がビジネスを運営します。 defaultencodingをutf-8に設定すると、コードはbyte_stringをutf-8として解釈できるため、データを破壊し、代わりにこれを返します。Angstrom(Ů)はビジネスを実行します。
定数を変更すると、依存するモジュールに劇的な影響を与えます。コードに出入りするデータを修正することをお勧めします。
次の例では、defaultencodingの設定がUTF-8の根本的な原因ではありませんが、問題がマスクされる方法と、入力エンコーディングが変更されたときにコードが明白な方法で中断する方法を示します: nicodeDecodeError: ' utf8 'コーデックは位置3131のバイト0x80をデコードできません:無効な開始バイト
#!/usr/bin/env python
#-*- coding: utf-8 -*-
u = u'moçambique'
print u.encode("utf-8")
print u
chmod +x test.py
./test.py
moçambique
moçambique
./test.py > output.txt
Traceback (most recent call last):
File "./test.py", line 5, in <module>
print u
UnicodeEncodeError: 'ascii' codec can't encode character
u'\xe7' in position 2: ordinal not in range(128)
シェルで動作し、sdtoutではなくsdtoutに送信するため、stdoutに書き込むための1つの回避策です。
Sys.stdout.encodingが定義されていない場合、つまり、stdoutに書き込むために最初にPYTHONIOENCODING = UTF-8をエクスポートする必要がある場合、実行されない他のアプローチを作成しました。
import sys
if (sys.stdout.encoding is None):
print >> sys.stderr, "please set python env PYTHONIOENCODING=UTF-8, example: export PYTHONIOENCODING=UTF-8, when write to stdout."
exit(1)
そのため、同じ例を使用します。
export PYTHONIOENCODING=UTF-8
./test.py > output.txt
働くでしょう
最初の危険はreload(sys)
にあります。
モジュールをリロードすると、実行時にモジュールのtwoコピーが実際に取得されます。古いモジュールは、他のすべてと同じPythonオブジェクトであり、それへの参照がある限り存続します。したがって、オブジェクトの半分は古いモジュールを指し、半分は新しいモジュールを指します。何らかの変更を加えた場合、ランダムなオブジェクトが変更を認識しない場合、それが表示されることはありません。
(This is IPython Shell)
In [1]: import sys
In [2]: sys.stdout
Out[2]: <colorama.ansitowin32.StreamWrapper at 0x3a2aac8>
In [3]: reload(sys)
<module 'sys' (built-in)>
In [4]: sys.stdout
Out[4]: <open file '<stdout>', mode 'w' at 0x00000000022E20C0>
In [11]: import IPython.terminal
In [14]: IPython.terminal.interactiveshell.sys.stdout
Out[14]: <colorama.ansitowin32.StreamWrapper at 0x3a9aac8>
さて、sys.setdefaultencoding()
固有
影響を受けるのは暗黙の変換str<->unicode
だけです。現在、utf-8
は地球上で最も安全なエンコーディングであり(ASCIIおよびすべてと下位互換性があります)、変換は「正常に動作します」、何が問題になる可能性がありますか?
まあ、何でも。それは危険です。
UnicodeError
に依存するコードや、エラーハンドラーでトランスコーディングを実行するコードが存在する可能性があります。これにより、予期しない結果が生成されます。そしてすべてのコードはデフォルト設定でテストされているため、ここでは「サポートされていない」領域に厳密になります、そしてコードの動作について保証する人はいません。