次のコードはPython 3:
_people = [u'Nicholas Gyeney', u'Andr\xe9']
writers = ", ".join(people)
print(writers)
print("Writers: {}".format(writers))
_
そして、次の出力を生成します。
_Nicholas Gyeney, André
Writers: Nicholas Gyeney, André
_
ただし、Python 2.7では、次のエラーが発生します。
_Traceback (most recent call last):
File "python", line 4, in <module>
UnicodeEncodeError: 'ascii' codec can't encode character u'\xe9'
in position 21: ordinal not in range(128)
_
", ".join(people)
を", ".join(people).encode('utf-8')
に変更することでこのエラーを修正できますが、そうすると、Python 3の出力は次のようになります。
_b'Nicholas Gyeney, Andr\xc3\xa9'
Writers: b'Nicholas Gyeney, Andr\xc3\xa9'
_
だから私は次のコードを使おうとしました:
_if sys.version_info < (3, 0):
reload(sys)
sys.setdefaultencoding('utf-8')
people = [u'Nicholas Gyeney', u'Andr\xe9']
writers = ", ".join(people)
print(writers)
print("Writers: {}".format(writers))
_
これにより、私のコードはすべてのバージョンのPythonで機能します。しかし、私はsetdefaultencoding
推奨されていません を使用してそれを読みました。
この問題に対処するための最良のアプローチは何ですか?
まず、Python 2.7および3.5バージョンをサポートすることを想定しています(2.6および3.0から3.2は少し異なる方法で処理されます)。
すでに読んだように、setdefaultencoding
は推奨されておらず、実際には必要ありません。
Unicodeテキストを処理するクロスプラットフォームコードを作成するには、通常、いくつかの場所で文字列エンコーディングを指定するだけで済みます。
# -*- coding: utf-8 -*-
_があります(コードにUnicodeテキストを含む文字列リテラルがある場合のみ)これらのルールに従って、例を変更した方法は次のとおりです。
_#!/usr/bin/env python
# -*- coding: utf-8 -*-
people = ['Nicholas Gyeney', 'André']
writers = ", ".join(people)
print(writers)
print("Writers: {}".format(writers))
print(type(writers))
print(len(writers))
_
出力:
_<type 'str'>
23
_
変更点は次のとおりです。
\xe9
_を実際のUnicode文字に置き換えました(_é
_)u
プレフィックスを削除しましたPython2.7.12および3.5.2でうまく機能します。
ただし、u
プレフィックスを削除すると、pythonはstr
ではなく通常のunicode
型を使用することに注意してください(print(type(writers))
の出力を参照)。 )。 _utf-8
_の場合、ほとんどの場所でUnicode文字列のように機能しますが、テキストの長さをチェックすると、間違った値が返されます。この例では、len
は_23
_を返します。実際の文字数は_22
_です。これは、基になる型がstr
であり、各バイトを文字としてカウントするためですが、文字_é
_は実際には2バイトである必要があります。
言い換えれば、これは(あなたの例のように)データをうまく出力するときに機能しますが、テキストに対して文字列操作をしたい場合には機能しません。この場合でも、文字列を操作する前に、u
プレフィックスを使用するか、データを明示的にUnicodeタイプに変換する必要があります。
したがって、単純な例ではない場合でも、u
プレフィックスを使用することをお勧めします。あなたは2つの場所でそれを必要とします:
_#!/usr/bin/env python
# -*- coding: utf-8 -*-
people = [u'Nicholas Gyeney', u'André']
writers = ", ".join(people)
print(writers)
print(u"Writers: {}".format(writers))
print(type(writers))
print(len(writers))
_
出力:
_<type 'unicode'>
22
_
注:u
プレフィックスはPython 3.0で削除され、下位互換性のためにPython 3.3で再導入されました。
Python 2でのUnicodeテキストの操作のすべての複雑さの詳細な説明は、公式ドキュメントで入手できます: Python 2-Unicode HOWTO 。
ファイルエンコーディングを指定する特別なコメントの抜粋を次に示します。
Pythonは、任意のエンコーディングでのUnicodeリテラルの記述をサポートしていますが、使用されているエンコーディングを宣言する必要があります。これは、ソースファイルの1行目または2行目に特別なコメントを含めることによって行われます。
_#!/usr/bin/env python # -*- coding: latin-1 -*- u = u'abcdé' print ord(u[-1])
_構文は、ファイルのローカル変数を指定するためのEmacsの表記法に触発されています。 Emacsは多くの異なる変数をサポートしていますが、Pythonは
coding
のみをサポートしています。 _-*-
_記号は、コメントが特別であることをEmacsに示します。 Pythonには意味がありませんが、慣例です。 Pythonはコメントで_coding: name
_または_coding=name
_を探します。このようなコメントを含めない場合、使用されるデフォルトのエンコーディングはASCIIになります。
「 Learning Python、5th Edition "」という本を手に入れたら、パートVIIIの第37章「Unicodeとバイト文字列」を読むことをお勧めします。高度なトピック。両方の世代のPythonでUnicodeテキストを操作するための詳細な説明が含まれています。
言及する価値のあるもう1つの詳細は、引数がformat
にあるかどうかに関係なく、フォーマット文字列がascii
の場合、ascii
は常にunicode
文字列を返すことです。
それとは逆に、_%
_を使用した古いスタイルのフォーマットでは、引数のいずれかがunicode
の場合、unicode
文字列が返されます。だからこれを書く代わりに
_print(u"Writers: {}".format(writers))
_
これを書くことができます。これは短くてきれいであるだけでなく、Python 2と3の両方で機能します:
_print("Writers: %s" % writers)
_
フォーマット時にUnicodeプレフィックスを指定できます。
print(u"Writers: {}".format(writers))
これで問題は解決しますが、Python 3スクリプトに不要なu''
プレフィックスが付いています。
バージョンを確認した後でfrom __future__ import unicode_literals
することもできますが、私はそうしません。u''
プレフィックスが十分に機能するため、一般的に操作が難しく、非推奨と見なされています。
Python2では、join
とprint
にUnicode文字列を使用する必要があります。
people = [u'Nicholas Gyeney', u'Andr\xe9']
writers = u", ".join(people)
print(writers)
print(u"Writers: {}".format(writers))
答えは、すべてをユニコードにすることです。
# -*- coding: utf-8 -*-
people = [u'Nicholas Gyeney', u'André']
writers = u", ".join(people)
print(writers)
print(u"Writers: {}".format(writers))