8

私は、Python(2.7)が私から隠しているものに分解された、Unicode文字列の問題を探すために数時間怒って過ごしましたが、それでも理解できません。最初にu".."、コードで一貫して文字列を使用しようとしましたが、その結果、悪名高いUnicodeEncodeError。を使ってみ.encode('utf8')ましたが、それも役に立ちませんでした。最後に、私も使用すべきではないことが判明し、すべてが自動的に機能します。しかし、私(ここでは私を助けてくれた友人にクレジットを与える必要があります)は、壁に頭をぶつけているときに何か奇妙なことに気づきました。asciisys.getdefaultencoding()返し、 UTF-8を返します。1.以下のコードでは、変更を加えなくても正常に動作します。2.を発生させます。デフォルトのシステムエンコーディングをで変更した場合 sys.stdout.encodingsysUnicodeEncodeErrorreload(sys).setdefaultencoding("utf8")、次に2.正常に動作します。私の質問は、そもそも2つのエンコーディング変数が異なる理由と、この単純なコードで間違ったエンコーディングを使用するにはどうすればよいのかということです。Unicode HOWTOに送らないでください。これは、についての数十の質問で明らかに読んだことがありUnicodeEncodeErrorます。

#  -*- coding: utf-8 -*-
import sys


class Token:
    def __init__(self, string, final=False):
        self.value = string
        self.final = final

    def __str__(self):
        return self.value

    def __repr__(self):
        return self.value

print(sys.getdefaultencoding())
print(sys.stdout.encoding)

# 1.
myString = "I need 20 000€."
tok = Token(myString)
print(tok)

reload(sys).setdefaultencoding("utf8")

# 2.
myString = u"I need 20 000€."
tok = Token(myString)
print(tok)
4

2 に答える 2

6

私の質問は、そもそも2つのエンコーディング変数が異なる理由です

それらは異なる目的を果たします。

sys.stdout.encoding端末がテキストを解釈するために使用するエンコーディングである必要があります。そうしないと、出力に文字化けが含まれる可能性があります。ある環境ではutf-8、別の環境ではcp437などです。

sys.getdefaultencoding()暗黙の変換のためにPython2で使用されます(エンコーディングが明示的に設定されていない場合)。つまり、Python 2はASCIIのみのバイト文字列とUnicode文字列を混在させることができます。たとえば、xml.etree.ElementTreeテキストをASCII範囲にバイト文字列として格納するかjson.dumps()、UnicodeではなくASCIIのみのバイト文字列を返します。 Python 2では(おそらくパフォーマンスのせいで)、ASCII文字を表すためにバイトはUnicodeよりも安価でした。Python 3では、暗黙的な変換は禁止されています。

sys.getdefaultencoding()'ascii'をオーバーライドしない限り、Python 2のすべてのシステムに常に存在します。オーバーライドしないと、バグが隠されたり、データのエンコードが間違っている可能性がある暗黙の変換によってデータが簡単に破損したりする可能性があります。

sys.getfilesystemencoding()ところで、 2つとは異なる可能性のある別の一般的なエンコーディングがあります。sys.getfilesystemencoding()OSデータ(ファイル名、コマンドライン引数、環境変数)のエンコードに使用されるエンコードである必要があります。

を使用して宣言されたソースコードエンコーディングは# -*- coding: utf-8 -*-、前述のすべてのエンコーディングとは異なる場合があります。

当然、ファイル、ネットワークからデータを読み取る場合、上記とは異なる文字エンコードを使用する場合があります。たとえば、メモ帳で作成されたファイルがWindows ANSIエンコーディングを使用して保存されている場合cp1252、別のシステムでは、すべての標準エンコーディングが異なる可能性があります。

重要なのは、Pythonとは関係のない理由で複数のエンコードが存在する可能性があり、頭痛の種を避けるために、Unicodeを使用してテキストを表現することです。入力時にできるだけ早くエンコードされたテキストをUnicodeに変換し、バイトにエンコードします(おそらく別のエンコードを使用)出力をできるだけ遅くします—これはいわゆるUnicodeサンドイッチの概念です。

この単純なコードで間違ったエンコーディングを使用するにはどうすればよいですか?

  1. 最初のコード例はうまくいきません。Python 2では、バイト文字列にASCII以外のリテラル文字を使用しますが、使用しないでください。バイト文字列のリテラルは、バイナリデータ(または必要に応じていわゆるネイティブ文字列)にのみ使用してください。I need 20 000Γé¼.Windowsコンソールなどのutf-8互換エンコーディングを使用しない環境で、Python 2を使用してコードを実行すると、コードが(文字ノイズに注意して)などの文字化けを生成する場合があります。

  2. 2番目のコード例は、がその一部ではないと仮定してreload(sys)問題ありません。u''すべての文字列リテラルの前に;を付けたくない場合。あなたが使うことができますfrom __future__ import unicode_literals

あなたの実際の問題はUnicodeEncodeErrorエラーでreload(sys)あり、正しい解決策ではありません!
正しい解決策は、POSIX(LANGLC_CTYPE)でロケールを適切に構成するか、出力がパイプ/ファイルにリダイレクトされる場合はenvvarを設定PYTHONIOENCODINGwin-unicode-consoleするか、インストールしてUnicodeをWindowsコンソールに出力することです。

于 2015-11-16T00:37:46.430 に答える
1

いくつかの標準コード(mailmanライブラリ)の同じ動作に気づきました。分析していただきありがとうございます。時間を節約するのに役立ちました。:-)問題はまったく同じです。私のシステムはを使用sys.getdefaultencoding()して取得しますがascii、これは1000個のUTF-8エンコード名のリストを処理するには不適切です。

stdin / stdoutと、ファイルシステムエンコーディング(utf-8)と、「defaultencoding」(ascii)との間に不一致があります。このスレッド:Python <3でUTF-8でエンコードされたテキストをコンソールに印刷する方法は?それがよく知られていて、Pythonのデフォルトのエンコーディングを変更していることを示しているようですか?より均質なもの(「utf-8どこでも」など)がハッシュ実装のような他のものを壊すといういくつかの兆候が含まれています。

そのため、デフォルトのエンコーディングを変更することも簡単ではありません。(さまざまな方法については、 http://blog.ianbicking.org/illusive-setdefaultencoding.htmlsysを参照してください。)ファイル内のインスタンスから削除されsite.pyます。

于 2013-09-14T06:29:34.990 に答える