3

誰かが私にPythonがこの振る舞いをする理由を説明できますか?

説明させてください。

バックグラウンド

Pythonをインストールしていて、ASCIIテーブルにない文字をいくつか使用したいと思います。そこで、Pythonのデフォルトのエンコードを変更します。そのようにして、すべての文字列をファイル.pyに保存します'_MAIL_TITLE_': u'Бронирование номеров',

ここで、辞書のキーを置き換えるメソッドを使用して、動的な方法で文字列をhtmlテンプレートに挿入したいと思います。

私はhtmlページのヘッダーに配置します:

<head>
 <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
 ...... <!-- Some Css's --> 
</head>

残念ながら、私のhtmlドキュメントは(それらが置き換えられた後)いくつかの間違った文字(変換されていない?誤って変換された?)で私に届きます

それで、私はターミナルを開いて、いくつかの注文をし始めます:

 1 - Python 2.4.6 (#1, Jan 27 2012, 15:41:03)
 2 - [GCC 4.1.2 20080704 (Red Hat 4.1.2-51)] on linux2
 3 - Type "help", "copyright", "credits" or "license" for more information.
 4 - >>> import sys
 5 - >>> sys.getdefaultencoding()
 6 - 'utf-8'
 7 - >>> u'èéòç'
 8 - u'\xe8\xe9\xf2\xe7'
 9 - >>> u'èéòç'.encode('utf-8')
10 - '\xc3\xa8\xc3\xa9\xc3\xb2\xc3\xa7'
11 - >>> u'è'
12 - u'\xe8'
13 - >>> u'è'.encode()
14 - '\xc3\xa8'

質問

行[7-10]を見てください。変じゃない?私の(6行目)Pythonにdefaultencodingがある場合、utf-89行目とは異なる方法でその文字列(7行目)を変換するのはなぜですか?次に、行[11-14]とその出力を見てください。

今、私は完全に混乱しています!

ヒント

そこで、入力ファイルの端末の方法(以前はISO-8859-1、現在はutf-8 )を変更しようとしましたが、何かが変更されました。

 1 - Python 2.4.6 (#1, Jan 27 2012, 15:41:03)
 2 - [GCC 4.1.2 20080704 (Red Hat 4.1.2-51)] on linux2
 3 - Type "help", "copyright", "credits" or "license" for more information.
 4 - >>> import sys
 5 - >>> sys.getdefaultencoding()
 6 - 'utf-8'
 7 - >>> u'èéòç'
 8 - u'\xc3\xc3\xa8\xc3\xa9\xc3\xb2\xc3\xa7'
 9 - >>> u'èéòç'.encode('utf-8')
10 - '\xc3\xa8\xc3\xa9\xc3\xb2\xc3\xa7'
11 - >>> u'è'
12 - u'\xe8'
13 - >>> u'è'.encode()
14 -'\xc3\xa8'

したがって、エンコーディング(明示的なエンコーディング)は入力エンコーディングとは独立して機能します(または、私には思えますが、これに何日も立ち往生しているので、頭がおかしくなったかもしれません)。

解決策はどこにありますか?

との8行目を見るbackgroundhint、作成されたUnicodeのオブジェクトにいくつかの違いがあることがわかります。それで、私はそれについて考え始めました。私は何を結論付けましたか?何もない。おそらく、私の.py(htmlドキュメントに挿入する必要のあるすべてのutf-8文字が含まれている)を保存すると、私のエンコーディングの問題がファイルのエンコーディングにあること以外は何もありません

「本当の」コード

このコードは特別なことは何もしません。htmlテンプレートを開き、文字列に配置し、プレースホルダーをユニコード(utf-8ed?wish yes)文字列に置き換え、インターネットから視覚化される別のファイルに保存します(yes、my "ランディング」ページは、ヘッダーutf-8の仕様に含まれています)。いくつかのファイルに散在しているため、ここにはコードがありませんが、プログラムのワークフローは確かです(トレースすることで)。

最後の質問

これに照らして、誰かが私のコードを機能させるためのアイデアを持っていますか?UNIXファイルエンコーディングについてのアイデア?または.pyファイルエンコーディング?コードを機能させるためにエンコーディングを変更するにはどうすればよいですか?

最後のヒント

プレースホルダーをutf-8オブジェクトに置き換える前に、

utf8Obj.encode('latin-1')

私のドキュメントはインターネットで完全に表示されます!

答えてくれた人たちに感謝します。

編集1-開発ワークフロー

これが私の開発ワークフローです。

そのプロジェクトのCVSがあります。プロジェクトはcentosOS上にあります。そのサーバーは64ビットマシンです。コードをEclipse付きのWindows7(64ビット)に開発します。すべての変更は、CVSコミットでのみコミットされます。このコードは、その種のPythonを使用するCentosマシンに適用されます。

Python 2.4.6 (#1, Jan 27 2012, 15:41:03)
[GCC 4.1.2 20080704 (Red Hat 4.1.2-51)] on linux2

私はEclipseをそのように動作するように設定しました:PREFERENCES-> GENERAL-> WORKSPACE-> TEXT FILE ENCODING:UTF-8

Zope / Ploneアプリケーションは同じサーバー上で実行されます:それはいくつかのPHPページを提供します。PHPページは、Zope / Ploneの「サーバー」にあるWSによるいくつかのPythonメソッド(アプリケーションロジック)を呼び出します。そのサーバーは、アプリケーションロジックに直接接続します。

それで全部です

EDIT2

これは、置換を行う関数です。

    def _fillTemplate(self, buf):
    """_fillTemplate(buf)-->str
    Ritorna il documento con i campi sostituiti con dict_template.
    """
    try:    
        for k, v in self.dict_template.iteritems():
            if not isinstance(v,unicode):
                v=str(v)
            else:
                v=v.encode('latin-1') #In that way it works, but why?
            buf = buf.replace(k, v)
4

3 に答える 3

5

この問題と将来の問題を解決するために、file にリダイレクトする際の UnicodeDecodeErrorに関する質問への回答を参照することをお勧めします。これには、このエンコーディング/デコーディング ビジネスとは何かについての一般的な説明が含まれています。


最初の例では、端末は Latin1 でエンコードします。

7 - >>> u'èéòç'
8 - u'\xe8\xe9\xf2\xe7'

これらの文字の Latin1 でのエンコードは、UTF-8 での同じ文字の有効なエンコードであるため、Python は変換を行う必要はありません。端末を UTF-8 に切り替えると、

7 - >>> u'èéòç'
8 - u'\xc3\xc3\xa8\xc3\xa9\xc3\xb2\xc3\xa7'

端末は、UTF-8 エンコーディングを 4 つの 2 バイト シーケンスとして Python に送信します。Python インタープリターは、これらのバイトを逐語的に取得して保持しました。これらは、文字列の有効なエンコード表現でもあります。実際、UTF-8 は同じ文字を複数の方法でエンコードできます。


エディターが UTF-8 で保存する場合は、.py ファイルの先頭に以下を追加する必要があります。

# -*- coding: utf-8 -*-

この行は、エディタで使用されるエンコーディングと一致する必要があります。


エンコーディングを処理するための最も堅牢なアプローチは、おそらく次の 2 つのいずれかです。

  1. プログラムは、単一のエンコーディングで内部 (バイト) 文字列のみを操作する必要があります (UTF-8 が適切な選択です)。これは、たとえば、Latin-1 でエンコードされたデータを取得した場合、UTF-8 に再エンコードする必要があることを意味します。

    data.decode('latin1').encode('utf8')
    

    この場合、文字列リテラルを処理する最善の方法は、エディターでファイルを UTF-8 で保存し、通常の (バイト) 文字列リテラル ( "This is a string"、前に nouを付けない) を使用することです。

  2. プログラムは、代わりに Unicode 文字列のみを操作できます。私の経験では、これは Python 2 では少し面倒です。ただし、Python 3 ではこれらのエンコーディングの問題をより自然にサポートしているため、これは私が Python 3 で選択した方法です (リテラル文字列は文字列であり、バイト文字列ではありません)。など)。

于 2012-03-09T09:26:04.703 に答える
5

あなたが私のコメントに答えている間、ここに最初の質問の答えがあります:

[7-10] 行を見てください。変じゃない?私の(6行目)pythonにutf-8のデフォルトエンコーディングがある場合、その文字列(7行目)を9行目とは異なる方法で変換するのはなぜですか?次に、[11-14] 行とその出力を見てください。

いいえ、変ではありません。Python エンコーディング、シェル エンコーディング、システム エンコーディング、ファイル エンコーディング、宣言されたファイル エンコーディング、および適用されたエンコーディングを区別する必要があります。多くのエンコーディングを行いますね。

sys.getdefaultencoding()

これにより、Python が Unicode 実装に使用するエンコーディングが得られます。これは出力とは関係ありません。

In [7]: u'è'
Out[7]: u'\xe8'
In [8]: u'è'.encode('utf8')
Out[8]: '\xc3\xa8'
In [9]: print u'è'
è
In [10]: print u'è'.encode('utf8')
è

を使用するprintと、文字が画面に出力されます。使用しない場合、Python は、同じデータを取得するためにコピー/貼り付けできる表現を提供します。

Unicode 文字列は utf8 文字列と同じではないため、同じデータは得られません。

Unicode は文字列の「ニュートラル」表現ですが、utf8 はエンコードされたものです。

于 2012-03-09T09:40:14.743 に答える
3

7 行目で、Unicode オブジェクトを出力します。

>>> u'èéòç'
u'\xe8\xe9\xf2\xe7'

エンコーディングは行われず、入力が Unicode コード単位\xe8、などで構成されていることが示されるだけです\xe9

11 行目で、Unicode オブジェクトから UTF-8 でエンコードされた文字列を作成します。エンコードされた文字列の出力は、エンコードされていない Unicode オブジェクトとは異なって見えますが、そうでないのはなぜでしょうか:

>>> u'èéòç'.encode('utf-8')
'\xc3\xa8\xc3\xa9\xc3\xb2\xc3\xa7'

端末のエンコーディングを変更した 2 番目の実験では、実際に入力文字の解釈を壊しました。

>>> u'èéòç'
u'\xc3\xa8\xc3\xa9\xc3\xb2\xc3\xa7'

これらの 4 文字を文字列に入れると、何らかの方法でどこかでエンコードされ、Python は、UTF-8 コード単位の 8 バイトを入力したと見なします。しかし、これらのバイトは、入力したい文字を表していません。Python は、実際には UTF-8 データを取得している間に、端末から ISO-8859-1 文字を取得すると考えているようで、混乱が生じます。

于 2012-03-09T10:13:52.790 に答える