Pythonで文字列によってUnicodeを宣言する理由


122

私はまだpythonを勉強していて、疑問があります:

Python 2.6.xでは、通常、このようなファイルヘッダーでエンコードを宣言します(PEP 0263の場合と同様)

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

その後、私の文字列はいつものように書かれています:

a = "A normal string without declared Unicode"

しかし、Pythonプロジェクトコードを見るたびに、エンコーディングがヘッダーで宣言されていません。代わりに、次のようにすべての文字列で宣言されます。

a = u"A string with declared Unicode"

違いは何ですか?これの目的は何ですか?Python 2.6.xはデフォルトでASCIIエンコーディングを設定することを知っていますが、ヘッダー宣言によってオーバーライドできるので、文字列ごとの宣言のポイントは何ですか?

補遺:ファイルのエンコーディングと文字列のエンコーディングを混同しているようです。説明してくれてありがとう:)


6
# coding: utf8十分ですが、必要ありません-*-
クラゲ

1
@jellyfish入力するつもりだったと思います# coding: utf-8
Samuel Harmer 2017

する必要があります#coding=utf-8python.org/dev/peps/pep-0263
Guangtong Shen

回答:


167

他の人が述べたように、これらは2つの異なるものです。

を指定すると# -*- coding: utf-8 -*-、Pythonに保存したソースファイルがであることを伝えますutf-8。Python 2のデフォルトはASCIIです(Python 3の場合はutf-8)。これは、インタープリターがファイル内の文字を読み取る方法に影響します。

一般的に、エンコーディングが何であれ、ファイルに高度なUnicode文字を埋め込むことはおそらく最善の方法ではありません。どちらのエンコーディングでも機能する文字列ユニコードエスケープを使用できます。


uように前にを付けて文字列を宣言するu'This is a string'と、Pythonコンパイラに文字列がバイトではなくUnicodeであることを伝えます。これはほとんどインタプリタによって透過的に処理されます。最も明らかな違いは、文字列にUnicode文字を埋め込むことができることです(つまり、u'\u2665'現在は正当です)。を使用from __future__ import unicode_literalsしてデフォルトにすることができます。

これはPython 2にのみ適用されます。Python 3では、デフォルトはUnicodeでありb、前にを指定する必要があります(b'These are bytes'たとえば、一連のバイトを宣言するため)。


説明ありがとう!これが最も完全なものなので、私はこれを受け入れられたものに設定します:)
Oscar Carballal

2
Python 2のデフォルトのソースエンコーディングはasciiです。
Mark Tolonen、2010

27
高いUnicode文字をファイルに埋め込むことは、実際には素晴らしいアイデアです。英語を母国語としない人は、文字列内のユニコードエスケープを読みたいとは思いません。
Mark Tolonen、2010

@Mark:ASCII修正をありがとう。私はすぐにPEP(python.org/dev/peps/pep-0263)を流用しましたが、これはプリアンブルでLatin-1について語っています。ほとんどの場合、ファイルに高度なUnicode文字を埋め込むのは良い考えではないと思います。確かに、ソースファイルで多くの英語以外の文字列をコーディングしている場合は簡単になりますが、通常はユーザーに表示するためにそれを行うので、おそらく別の場所で定義する必要があります。また、1つの誤って構成されたテキストエディターは、これらすべての文字を破壊する可能性があります。
Chris B.

4
i18nalizedアプリをプログラミングしている場合は同意しますが、中国語またはフランス語のプログラマーかどうかを検討してください。文字列だけでなく、コメントも同様です。Pythonがソースエンコーディングに柔軟に対応できるのは素晴らしいことです。Python 3では、変数名に非ASCII文字を含めることもできます。
Mark Tolonen、2010

23

他の人が言ったように# coding:、ソースファイルが保存されるエンコーディングを指定します。これを説明するための例をいくつか示します。

cp437(コンソールのエンコーディング)としてディスクに保存されたファイルですが、エンコーディングが宣言されていません

b = 'über'
u = u'über'
print b,repr(b)
print u,repr(u)

出力:

  File "C:\ex.py", line 1
SyntaxError: Non-ASCII character '\x81' in file C:\ex.py on line 1, but no
encoding declared; see http://www.python.org/peps/pep-0263.html for details

# coding: cp437追加されたファイルの出力:

über '\x81ber'
über u'\xfcber'

最初、Pythonはエンコーディングを認識しておらず、非ASCII文字について不満を述べていました。エンコーディングがわかると、バイト文字列は実際にディスク上にあるバイトを取得します。Unicode文字列の場合、Pythonは\ x81を読み取り、cp437でそれがüであることを認識し、それをüの Unicodeコードポイントにデコードしました。(U + 00FC)にデコードしました。バイト文字列が出力されると、Pythonは16進値81をコンソールに直接送信しました。Unicode文字列が印刷された場合には、Pythonは正しくCP437としての私のコンソールエンコーディングを検出し、Unicodeの翻訳üをためCP437値にü

UTF-8で宣言および保存されたファイルの処理は次のとおりです。

├╝ber '\xc3\xbcber'
über u'\xfcber'

UTF-8では、üは16進バイトとしてエンコードされるC3 BCため、バイト文字列にはそれらのバイトが含まれますが、Unicode文字列は最初の例と同じです。Pythonは2バイトを読み取り、正しくデコードしました。Pythonはバイト文字列を誤って出力しました。これは、üを表す2つのUTF-8バイトが直接cp437コンソールに送信されたためです。

ここでは、ファイルはcp437と宣言されていますが、UTF-8で保存されています。

├╝ber '\xc3\xbcber'
├╝ber u'\u251c\u255dber'

バイト文字列は引き続きディスク上のバイト(UTF-8 hex bytes C3 BC)を取得しましたが、それらを単一のUTF-8エンコード文字ではなく2つのcp437文字として解釈しました。これらの2つの文字はUnicodeコードポイントに変換され、すべてが正しく印刷されません。


10

これは文字列のフォーマットを設定しません。ファイルのフォーマットを設定します。そのヘッダーを使用して"hello"も、バイト文字列であり、Unicode文字列ではありません。Unicodeにするためには、u"hello"どこでも使用する必要があります。ヘッダーは、.pyファイルを読み取るときに使用する形式のヒントにすぎません。


その時私は間違っていた、彼らは同じだと思った。ユニコード文字列の使用はi18nですか?
Oscar Carballal

@オスカー:はい、大部分は。Djangoなどを使用してWebサイトを作成していて、ASCII以外の文字を持つ人々を処理する必要がある場合、それは別の使用方法です。
icktoofay 2010

7

ヘッダー定義は、コード自体のエンコードを定義するためのものであり、実行時に生成される文字列ではありません。

۲のような非ASCII文字をPythonスクリプトにutf-8ヘッダー定義なしで置くと警告がスローされます

エラー


-1

変数を変換できるように、unicoderという次のモジュールを作成しました。

import sys
import os

def ustr(string):

    string = 'u"%s"'%string

    with open('_unicoder.py', 'w') as script:

        script.write('# -*- coding: utf-8 -*-\n')
        script.write('_ustr = %s'%string)

    import _unicoder
    value = _unicoder._ustr

    del _unicoder
    del sys.modules['_unicoder']

    os.system('del _unicoder.py')
    os.system('del _unicoder.pyc')

    return value

次に、プログラムで次のことを実行できます。

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

from unicoder import ustr

txt = 'Hello, Unicode World'
txt = ustr(txt)

print type(txt) # <type 'unicode'>
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.