1

Unicode と文字列のエンコーディングは、まだ頭痛の種です。この質問/回答に従って、メッセージに特殊文字 (äÄÜ..) を追加できるようにしました。

次の構造では、バージョン 2 が機能し、バージョン 1 が機能しない理由を理解するのに苦労しています。

私のモデル:

# -*- coding: utf-8 -*-
from __future__ import unicode_literals

class Project(models.Model):
    """
    Representation of a project
    """

    name = models.CharField(max_length=200)

    def __unicode__(self):
            return '%s ' % (self.name)

バージョン 1:

# -*- coding: utf-8 -*-
from __future__ import unicode_literals

def print_project(self, project):
        project_prefix = "Project: "
        print (project_prefix + str(project))

バージョン 2:

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

def print_project(self, project):
        project_prefix = "Project: "
        print (project_prefix + str(project))

ご覧のとおり、唯一の違いは、このfrom __future__ import unicode_literalsインポートを行うことです。スローされるエラーは次のとおりです。

'ascii' codec can't decode byte 0xc3 in position 0: ordinal not in range(128)
4

1 に答える 1

3

その__future__ステートメントの後、リテラルはstrオブジェクトではなくunicodeオブジェクトです。それが声明の要点です。__future__これについては、ドキュメントや彼らが参照するPEP 3112bytes (文字列リテラルが現在 Unicode であることを考えると、Python 2 スタイルのオブジェクトの書き方についてほとんどの時間を費やしています) のいずれにもあまり詳しく説明されていません)。しかし、それはそれがすることです。

対話型インタープリターでこれをテストできます。

>>> 'abc'
'abc'
>>> from __future__ import unicode_literals
>>> 'abc'
u'abc'

したがって、バージョン 2 では、2 つのstrオブジェクトを一緒に追加しますが、これは簡単です。しかし、バージョン 1 では、 aunicodeと aを追加していstrます。strこれは、デフォルトのエンコーディングである ASCII を使用して を に自動的に変換することで機能しunicodeますが、これは機能しません。


これを修正する最も簡単な方法はproject、 a をunicodeそれ自体にすることです。

def print_project(self, project):
    project_prefix = "Project: "
    print (project_prefix + unicode(project))

実際、これは__future__ステートメントの有無にかかわらず機能します— with it, project_prefixis already unicode; それがなければ、strASCII からデコードされますが、ASCII であるため問題ありませ

非 ASCII リテラルを (project_prefix で) 使用したい場合、およびコードを__future__ステートメントの有無にかかわらず機能させたい場合は、手動でデコードする必要があります。

def print_project(self, project):
    project_prefix = "Project: ".decode('utf-8')
    print (project_prefix + unicode(project))

(もちろん、ソース ファイルのコーディング宣言と一致していることを確認してください。)


コメントでは、次のように尋ねます。

import ステートメントを使用する場合__future__、.py ファイルの先頭でコーディングを定義する必要がありますか? # -- コーディング: utf-8 --

短い答えはイエスです。

ドキュメントがこれをどこかで直接カバーしているかどうかはわかりませんが、考えてみれば、それ以外に機能する方法はありません。

8 ビット ソース コードのリテラルを Unicode として解釈するために、Python コンパイラはそれらをデコードする必要があります。それらを何からデコードするかを知る唯一の方法は、コーディング宣言です。

これを別の見方で見ると、この__future__ステートメントは、文字列リテラルに関する限り Python 2 を Python 3 のように動作させ、Python 3 はコーディング宣言を必要とするということです。

これを自分でテストしたい場合は、以下を UTF としてコピーし、テキスト ファイルに貼り付けます。(これを行うには、コーディング宣言を理解しないエディターを使用する必要があることに注意してください — emacs のようなものは、保存時に UTF-8 テキストを Latin-1 に変換する場合があります!)。

# -*- coding: latin-1 -*-
from __future__ import unicode_literals
print repr('é')

これを実行すると、u'\xc3\xa9'ではなくが出力されu'\xe9'ます。

コーディングを指定しない場合、Python 3 はデフォルトで UTF-8 になりますが、Python 2.5-2.7 はunicode_literals. したがって、コーディング宣言が必要です。(3.x であっても、常に安全に追加できます。また、多くのプログラマーのテキスト エディターを満足させるものでもあります。そのため、Latin-1 や Shift-JIS を誰も覚えていない未来に到達するまで、維持する価値のある習慣かもしれません。 cp1250 など)。

于 2013-06-11T19:29:57.173 に答える