コンソールからアプリケーションを実行すると、 Python で多くの「エンコードできない」および「デコードできない」問題が発生します。しかし EclipsePyDev IDEでは、デフォルトの文字エンコーディングは TF-8 に設定されており、問題ありません。
デフォルトのエンコーディングを設定するために検索しましたが、人々はPythonが起動時にsys.setdefaultencoding
関数を削除し、それを使用できないと言います。
それで、それに対する最善の解決策は何ですか?
以下は、sys
から削除されたsetdefaultencoding()
関数を返す簡単なメソッド(ハック)です。
import sys
# sys.setdefaultencoding() does not exist, here!
reload(sys) # Reload does the trick!
sys.setdefaultencoding('UTF8')
これは安全なことではありませんが:Pythonのときにsys.setdefaultencoding()
がsys
から意図的に削除されるため、これは明らかにハックです開始します。それを再度有効にしてデフォルトのエンコーディングを変更します デフォルトであるASCIIに依存するコードを壊すことができます (このコードはサードパーティである可能性があり、一般に修正が不可能または危険になります)。
スクリプトの出力をパイプ/リダイレクトしようとしたときにこのエラーが発生した場合
UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-5: ordinal not in range(128)
コンソールでPYTHONIOENCODINGをエクスポートして、コードを実行するだけです。
export PYTHONIOENCODING=utf8
A)sys.getdefaultencoding()
の出力を制御するには:
python -c 'import sys; print(sys.getdefaultencoding())'
ascii
それから
echo "import sys; sys.setdefaultencoding('utf-16-be')" > sitecustomize.py
そして
PYTHONPATH=".:$PYTHONPATH" python -c 'import sys; print(sys.getdefaultencoding())'
utf-16-be
PYTHONPATH
でsitecustomize.pyを高くすることができます。
また、 reload(sys).setdefaultencoding
by @EOLを試してみたいかもしれません
B)stdin.encoding
およびstdout.encoding
を制御するには、PYTHONIOENCODING
を設定します:
python -c 'import sys; print(sys.stdin.encoding, sys.stdout.encoding)'
ascii ascii
それから
PYTHONIOENCODING="utf-16-be" python -c 'import sys;
print(sys.stdin.encoding, sys.stdout.encoding)'
utf-16-be utf-16-be
最後に:A)またはB)またはboth!
PyDev 3.4.1以降、デフォルトのエンコーディングは変更されていません。詳細については this ticket をご覧ください。
以前のバージョンの解決策は、PyDevがデフォルトのエンコーディングとしてUTF-8で実行されないようにすることです。 Eclipseで、ダイアログ設定を実行します(正しく覚えていれば「実行構成」)。共通タブでデフォルトのエンコードを選択できます。これらのエラーを「初期」にしたい場合はUS-ASCIIに変更してください(つまり、PyDev環境で)。 この回避策の元のブログ投稿 も参照してください。
Python2(およびpython2のみ)に関して、以前の回答のいくつかは、次のハックの使用に依存しています。
import sys
reload(sys) # Reload is a hack
sys.setdefaultencoding('UTF8')
使用しないことをお勧めします(チェック this または this )
私の場合、副作用があります。ipythonノートブックを使用しています。コードを実行すると、「print」関数が機能しなくなります。私はそれに対する解決策があると思いますが、それでもハックを使用することは正しい選択肢ではないはずです。
多くのオプションを試した後、私のために働いたものは、sitecustomize.py
で同じコードを使用することでした。コードの一部はそのモジュールを評価した後、setdefaultencoding関数はsysから削除されます。
そのため、解決策は、ファイル/usr/lib/python2.7/sitecustomize.py
にコードを追加することです。
import sys
sys.setdefaultencoding('UTF8')
Virtualenvwrapperを使用する場合、編集するファイルは~/.virtualenvs/venv-name/lib/python2.7/sitecustomize.py
です。
そして、pythonノートブックとcondaで使用すると、~/anaconda2/lib/python2.7/sitecustomize.py
になります。
それについての洞察力に富んだブログ投稿があります。
https://anonbadger.wordpress.com/2015/06/16/why-sys-setdefaultencoding-will-break-code/ を参照してください。
以下にその内容を言い換えます。
文字列のエンコードに関してそれほど強く型付けされていなかったpython 2では、異なるエンコードされた文字列に対して操作を実行でき、成功します。例えば。以下はTrue
を返します。
u'Toshio' == 'Toshio'
これは、sys.getdefaultencoding()
でエンコードされたすべての(通常の、接頭辞なしの)文字列に適用され、デフォルトではascii
になりますが、他の文字列には適用されません。
デフォルトのエンコーディングは、site.py
でシステム全体で変更されることを意図していましたが、他の場所では変更されませんでした。ユーザーモジュールに設定するためのハック(ここでも説明します)は、ハッキングであり、ソリューションではありません。
Python 3はシステムエンコーディングをデフォルトのutf-8に変更しましたが(LC_CTYPEがユニコード対応の場合)、基本的な問題は、ユニコード文字列で使用されるたびに「バイト」文字列を明示的にエンコードする要件で解決されました。
最初:reload(sys)
と、出力ターミナルストリームの必要性に関するランダムなデフォルトエンコーディングの設定は、悪い習慣です。 reload
は多くの場合、環境に応じて適切に配置されているsysの内容を変更します。 sys.stdin/stdoutストリーム、sys.excepthookなど.
Sys.stdoutでのprint
'ingユニコード文字列およびASCIIを超えるstr
のエンコード問題(リテラルからなど)を解決するために知っている最良の解決策は、次のとおりです。必要に応じてオプションで許容:
何らかの理由でsys.stdout.encoding
がNone
であるか、存在しないか、誤ってfalseであるか、stdout端末またはストリームが実際に可能なものよりも「少ない」場合、正しい.encoding
属性を指定してください。最後に、sys.stdout & sys.stderr
をファイルのような翻訳オブジェクトに置き換えることにより。
ターミナル/ストリームが発生するすべてのユニコード文字をまだエンコードできない場合、およびそのためにprint
を壊したくない場合は、ファイルに似たオブジェクトを変換するときにエンコードを置換する動作を導入できます。
次に例を示します。
#!/usr/bin/env python
# encoding: utf-8
import sys
class SmartStdout:
def __init__(self, encoding=None, org_stdout=None):
if org_stdout is None:
org_stdout = getattr(sys.stdout, 'org_stdout', sys.stdout)
self.org_stdout = org_stdout
self.encoding = encoding or \
getattr(org_stdout, 'encoding', None) or 'utf-8'
def write(self, s):
self.org_stdout.write(s.encode(self.encoding, 'backslashreplace'))
def __getattr__(self, name):
return getattr(self.org_stdout, name)
if __== '__main__':
if sys.stdout.isatty():
sys.stdout = sys.stderr = SmartStdout()
us = u'aouäöüфżß²'
print us
sys.stdout.flush()
グローバルなデフォルトのエンコーディングを(UTF-8のみに)変更する唯一の正当な理由は、アプリケーションに関するものだと思いますソースコード決定-I/Oストリームエンコーディングの問題ではなく、常にu'string'
スタイルのUnicodeエスケープを使用せずに、文字列リテラルをコードに変換します。これはPython 2またはPython 2 + 3のソースコードベースを処理することにより、(anonbadgerの記事に書かれていることにもかかわらず)かなり一貫して行うことができます。 asciiまたはUTF-8プレーン文字列リテラルを一貫して使用します-それらの文字列が潜在的にサイレントUnicode変換を受け、モジュール間を移動するか、潜在的にstdoutに移動する限り。そのためには、「# encoding: utf-8
」またはascii(宣言なし)をお勧めします。 chr#127(今日ではまれです)を超えるASCIIデフォルトエンコーディングエラーに致命的に依存しているライブラリを変更またはドロップします。
そして、上記のSmartStdout
スキームに加えて、アプリケーションの起動時に(および/またはsitecustomize.pyを介して)このようにします-reload(sys)
を使用せずに:
...
def set_defaultencoding_globally(encoding='utf-8'):
assert sys.getdefaultencoding() in ('ascii', 'mbcs', encoding)
import imp
_sys_org = imp.load_dynamic('_sys_org', 'sys')
_sys_org.setdefaultencoding(encoding)
if __== '__main__':
sys.stdout = sys.stderr = SmartStdout()
set_defaultencoding_globally('utf-8')
s = 'aouäöüфżß²'
print s
このように、文字列リテラルとほとんどの操作(文字の繰り返しを除く)は、Unicode変換をPython3のみのように考えることなく快適に動作します。もちろん、ファイルI/Oは、Python3の場合と同様に、エンコードに関して常に特別な注意が必要です。
注:プレーン文字列は、utf-8からSmartStdout
のUnicodeに暗黙的に変換されてから、出力ストリームエンコーディングに変換されます。
これで問題が解決しました。
import os
os.environ["PYTHONIOENCODING"] = "utf-8"
これは、python2とpython3の両方と互換性があり、常に生成されるコードを生成するために使用したアプローチですutf8出力。他の場所でこの答えを見つけましたが、ソースを思い出せません。
このアプローチは、sys.stdout
をファイルのようなものではありませんに置き換えます(ただし、標準ライブラリ内のもののみを使用します)。これは基礎となるライブラリに問題を引き起こす可能性がありますが、sys.stdout outがフレームワークでどのように使用されるかを適切に制御できる単純な場合、これは合理的なアプローチです。
sys.stdout = io.open(sys.stdout.fileno(), 'w', encoding='utf8')
これは、(1)Windowsプラットフォームで(2)Python 2.7を実行し、(3)素敵なソフトウェア(つまり、あなたによって書かれていないためすぐにエンコード/デコード印刷操作の候補)は、IDLE環境で「きれいなユニコード文字」を表示しません(Pythonwinはユニコードを印刷します)。たとえば、Stephan Boyerが教育学の証明者からの出力で使用するきちんとしたFirst Order Logicシンボル First Order Logic Prover 。
システムを強制的にリロードするという考えが気に入らず、システムにPYTHONIOENCODINGなどの環境変数の設定に協力させることができませんでした(直接Windows環境変数を試し、site-packagesのsitecustomize.pyにそれを1つとしてドロップしました)ライナー= 'utf-8')。
そのため、成功への道をハッキングする意思がある場合は、通常IDLEディレクトリに移動します。「C:\ Python27\Lib\idlelib」ファイルIOBinding.pyを見つけます。そのファイルのコピーを作成し、別の場所に保存して、選択したときに元の動作に戻すことができるようにします。エディター(例:IDLE)でidlelibのファイルを開きます。このコード領域に移動します。
# Encoding for file names
filesystemencoding = sys.getfilesystemencoding()
encoding = "ascii"
if sys.platform == 'win32':
# On Windows, we could use "mbcs". However, to give the user
# a portable encoding name, we need to find the code page
try:
# --> 6/5/17 hack to force IDLE to display utf-8 rather than cp1252
# --> encoding = locale.getdefaultlocale()[1]
encoding = 'utf-8'
codecs.lookup(encoding)
except LookupError:
pass
言い換えると、エンコーディング変数をlocale.getdefaultlocaleに等しくしていた 'try'に続く元のコード行をコメントアウトします(これにより、不要なcp1252が得られるため)、代わりにブルートフォースで 'utf-8'にします(行 'encoding =' utf-8)を追加しますように)。
これはstdoutへのIDLE表示にのみ影響し、ファイル名などに使用されるエンコーディング(以前のファイルシステムエンコーディングで取得された)には影響しないと思います。後でIDLEで実行する他のコードに問題がある場合は、IOBinding.pyファイルを元の変更されていないファイルに置き換えるだけです。