0

現在、Linux (Ubuntu) でのコーディング/エンコーディングに重大な問題があります。以前はこれに対処する必要がなかったので、なぜこれが実際に機能しないのかわかりません!

/usr/share/applications/*.desktopからファイルを解析し、HTTPServer 経由で Web ブラウザーに表示される情報を抽出しています。テンプレートに使用しています。jinja2

最初に、私はそれを言っUnicodeDecodeErrorた電話で受け取りましたjinja2.Template.render()

utf-8 cannot decode character XXX at position YY [...]

appfindそのため、 -module (*.desktopファイルを解析する)からのすべての値を作成し、Unicode 文字列のみを返しました。

この場所の問題はこれまでのところ解決されていますが、ある時点で、関数によって返された文字列をBaseHTTPServer.BaseHTTTPRequestHandler.wfileスロットに書き込んでいます。使用するエンコーディングに関係なく、このエラーを修正できません。

この時点で、書かれている文字列は、おそらく、Unicode オブジェクトを返すものからwfile来ています。jinja2.Template.render()

奇妙な部分は、私のUbuntu 12.04 LTS では動作しているが、友人のUbuntu 11.04 LTS では動作していないことです。しかし、それが理由ではないかもしれません。*.desktop彼はさらに多くのアプリケーションを持っており、ファイルでエラーを発生させるエンコーディングを使用している可能性があります。

ただし、*.desktopファイルのエンコーディングを適切に確認しました。

data = dict(parser.items('Desktop Entry'))

try:
    encoding = data.get('encoding', 'utf-8')
    result = {
        'name':       data['name'].decode(encoding),
        'exec':       DKENTRY_EXECREPL.sub('', data['exec']).decode(encoding),
        'type':       data['type'].decode(encoding),
        'version':    float(data.get('version', 1.0)),
        'encoding':   encoding,
        'comment':    data.get('comment', '').decode(encoding) or None,
        'categories': _filter_bool(data.get('categories', '').
                                        decode(encoding).split(';')),
        'mimetypes':  _filter_bool(data.get('mimetype', '').
                                        decode(encoding).split(';')),
    }

# ...

このエラーを修正する方法を教えてください。私はunicode()常に使用する必要がある SO に関する回答を読みましたが、それを実装するのは非常に面倒であり、書き込み時に問題が解決するとは思いませんwfileか?

ありがとう、
ニクラス

4

4 に答える 4

3

これはおそらく明らかですが、とにかく: wfile は通常のバイトストリームです: 書き込まれるものはすべて、書き込まれるときに unicode.encode():ed でなければなりません。

OPを読んで、正確に何が進行中なのかはっきりしません。ただし、エンコーディングの問題をデバッグするのに役立つことがわかったいくつかのトリックがあります。これがあなたがずっと前に超越したものである場合は、事前にお詫び申し上げます。

  • cat -vこれは、ファイルが実際に持っているエンコーディングを決定するために私が見つけた唯一の確実な方法です。UTF-8 非 ASCII 文字はマルチバイトです。つまり、複数の '^' エントリのシーケンスになることを意味しcat -vます。

  • シェル環境 (LC_ALL など) は、私の経験では、問題の最も一般的な原因です。UTF-8 と latin-1 の両方が利用可能なロケールを持つシステムがあることを確認してください。LC_ALL を、エンコーディングを明示的に指定するロケールに常に設定しますLC_ALL=sv_SE.iso88591

  • bash と zsh では、次のように、そのコマンドの特定の環境を変更してコマンドを実行できます。

    $ LC_ALL=sv_SE.utf8 python ./foo.py
    

    これにより、さまざまなロケールをエクスポートするよりもテストがはるかに簡単になり、シェルを汚染することもありません。

  • 内部にユニコード文字列があると仮定しないでください。文字列が Unicode であることを確認する assert ステートメントを記述します。

    assert isinstance(foo, unicode)
    
  • 使用しているエンコーディングで、一般的な文字の壊れた/誤って表現されたバージョンを認識する方法を学びます。たとえば、'\xe4' は latin-1 のダイアレシスであり、'ä' はダイアレシスを構成する 2 つの UTF-8 バイトであり、誤って latin-1 で表されます。この種のゴープを知っていると、デバッグのエンコーディングの問題が大幅に削減されることがわかりました。

于 2012-06-07T19:59:34.123 に答える
1

バイト文字列とUnicode文字列には統制のとれたアプローチをとる必要があります。これはそれをすべて説明します: 実用的なUnicode、または、どうすれば痛みを止めることができますか?

于 2012-06-08T21:50:30.033 に答える
0

スニペット内のすべての出現箇所で.encode(encoding)代わりに使用してみてください。.decode(encoding)

于 2012-06-08T21:19:28.140 に答える
0

デフォルトでは、Python が unicde でエンコーディングの問題に遭遇すると、エラーがスローされます。ただし、この動作は、エラーが予想されるか、重要でない場合などに変更できます。

ascii のスーパーセットである 2 つの Unicode ページ間で変換しているとします。どちらもほとんど同じ文字ですが、1 対 1 の対応はありません。したがって、エラーを無視する必要があります。

これを行うにerrorsは、encode 関数で変数を使用します。

mystring = u'This is a test'
print mystring.encode('utf-8', 'ignore')
print mystring.encode('utf-8', 'replace')
print mystring.encode('utf-8', 'xmlcharrefreplace')
print mystring.encode('utf-8', 'backslashreplace')

読み取り/書き込み時に間違ったエンコーディングが使用されている場合、Unicode には多くの問題があります。Unicode 文字列を取得したら、必ずjinja2 が必要とする Unicodeの形式に変換してください。

これで問題が解決しない場合は、表示されている 2 番目のエラーを追加してください。何が起こっているのかを明確にするコード スニペットを添えてください。

于 2012-06-07T20:44:20.340 に答える