スクリプトの上部でこれを使用するpyスクリプトをいくつか見ました。どのような場合に使用する必要がありますか?
import sys
reload(sys)
sys.setdefaultencoding("utf-8")
スクリプトの上部でこれを使用するpyスクリプトをいくつか見ました。どのような場合に使用する必要がありますか?
import sys
reload(sys)
sys.setdefaultencoding("utf-8")
回答:
ドキュメントのとおり:これにより、デフォルトのASCIIからUTF-8などの他のエンコーディングに切り替えることができます。これは、Pythonランタイムが文字列バッファをユニコードにデコードする必要があるときにいつでも使用します。
この関数は、Pythonが環境をスキャンするPythonの起動時にのみ使用できます。システム全体のモジュールで呼び出す必要があります。sitecustomize.py
このモジュールが評価された後、setdefaultencoding()
関数はsys
モジュールから削除されます。
実際にそれを使用する唯一の方法は、属性を元に戻すリロードハックを使用することです。
また、の使用sys.setdefaultencoding()
は常に推奨されておらず、py3kでは何も行われなくなりました。py3kのエンコーディングは「utf-8」に固定されており、変更するとエラーが発生します。
私は読むためのいくつかの指針を提案します:
sys.stdout
、それは持っていたときにNone
Pythonプログラムの出力をリダイレクトするときのようなエンコーディングを、)。
sys.setdefaultencoding()
は常に推奨されていません
UTF-8
。ハードワイヤードではなく、常にそうであるとは限りません。 LC_ALL=en_US.UTF-8 python3 -c 'import sys; print(sys.stdout.encoding)'
与えるUTF-8
がLC_ALL=C python3 -c 'import sys; print(sys.stdout.encoding)'
与えるANSI_X3.4-1968
(またはおそらく他の何か)
答えは絶対にありません!(あなたが本当にあなたが何をしているかを知っているのでない限り)
解法の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)
これらは私にとっては機能しますが、UTF-8を使用しない人にとっては必ずしも機能するとは限りません。デフォルトのASCIIは、エンコーディングの前提がコードに組み込まれていないことを保証しますsys.setdefaultencoding("utf-8")
またsys.setdefaultencoding("utf-8")
sys.stdout.encoding
、コンソールに文字を出力するときに使用されるfixのように見えるという副作用もあります。Pythonは、ユーザーのロケール(Linux / OS X / Un * x)またはコードページ(Windows)を使用してこれを設定します。時々、ユーザーのロケールが壊れ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に設定することは根本的な原因ではありませんが、問題がどのようにマスクされ、入力エンコーディングが変更されたときに、コードが明白な方法で壊れるのかを示しています: UnicodeDecodeError: 'utf8' codec can位置3131のバイト0x80をデコードしない:無効な開始バイト
sys.setdefaultencoding("utf-8")
、コードをPython 3のように動作させるのは良いことです。現在は2017年です。2015年に回答を書いても、後ろ向きではなく前向きに考えた方がいいと思います。出力がリダイレクトされるかどうかに応じて、Python 2でのコードの動作が異なることがわかったとき、これは実際には最も簡単な解決策でした(Python 2の非常に厄介な問題)。言うまでも# coding: utf-8
ありませんが、既にがあり、Python 3の回避策は必要ありません(setdefaultencoding
バージョンチェックを使用してマスクする必要があります)。
sys.setdefaultencoding("utf-8")
、Py 2.xコードをPython 3と互換性がありません。デフォルトのエンコーディングがASCIIであると想定している外部モジュールも修正しません。コードをPython 3互換にすることは非常に簡単で、この厄介なハックは必要ありません。これは非常に現実的な問題が発生する理由例えば、Amazonはこの仮定をいじって私の経験を参照してください。stackoverflow.com/questions/39465220/...
PYTHONIOENCODING="UTF-8"
私のPython2.7 Django-1.11環境を支援しました。ありがとう。
detect_encoding
。
detect_encoding
が言語の手がかりに基づいて文字列のエンコーディングを検出できる方法だと想像してください。
#!/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 notに送信するので、これはstdoutに書き込むための1つの回避策です。
sys.stdout.encodingが定義されていない場合は実行されない別のアプローチを作成しました。つまり、標準出力に書き込むには、最初にエクスポート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)
。
モジュールをリロードすると、実際にはランタイムでモジュールのコピーが2つ取得されます。古いモジュールは他のすべてと同様に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
非ASCII入力に対してスローされることに依存するコード、またはエラーハンドラーでトランスコーディングを行うコードが存在する可能性があります。これにより、予期しない結果が生じます。また、すべてのコードはデフォルト設定でテストされているため、ここでは厳密に「サポートされていない」領域にあり、コードの動作を保証するものは誰もいません。