いくつかの時間のためのPythonを使用した後、私は、PythonのUnicodeはやや混乱していたので、ここで私は私の主な理解のいくつかを共有したいと思います。
Pythonの3のみがあった場合はPython 3文字列の意味は非常に明確であるため、簡単に言えば、人生は、ずっと幸せになります。しかし、現実は時々そのきちんとしていない、と私たちは、従来の問題点(パイソン2)に対処するしかありません。
データ型の違い
混乱の主な原因の一つは、表現するために使用される実際のデータ型の違いによるものであるstr
のPython 2では、:パイソン2及び図3にstr
ありbytes
、そしてUnicode文字列ですunicode
。Pythonでは、str
これはUnicode文字列は、で表されたUnicodeは、よく、ではないstr
、そこにあるそのような組み込みの名前付きの型unicode
すべてで。多くの混乱が発生する場所です。
次の表は、Python 2と3で異なるデータタイプの関係を示す図です。
タイプ | Pythonの2 | Pythonの3 |
---|---|---|
バイト | str |
bytes |
ユニコード | unicode |
str |
Bytes
使用リテラルがあり、常に b'ascii'
Pythonの2と3の両方で、物事が再びための複雑な取得Unicode
データの種類:
そして、どのようにユビキタスについて平野のような文字列リテラル'plain'
のPython 2で?まあ、その意味は、次の行は、Pythonのソースファイルの先頭に存在するかどうかによって異なります。
from __future__ import unicode_literals
- 上記の行が存在しない場合、
'plain'
バイトとして扱われる(bytes
/str
パイソン2) - 上記の行が存在する場合、
'plain'
Unicodeとして扱われる(unicode
パイソン2)
あなたは上記を理解するのであれば、うまくいけば、あなたは古いの/他のコードを読み取るので、混同しないでしょう。
どのようにあなたが2と3の互換性の両方をする新しいPythonプログラムを書くことについてはどうですか?まあ、私の提案は、このようなものです:
常に使う
from __future__ import unicode_literals
文を。
主な利点それが同じ意味を与えるということであるplain
Pythonの2と3の両方で文字列リテラル、およびUnicodeを使用すると、おそらく文字列のハンドリングにおける最善の策です。
エンコードとデコード
- エンコード:変換
string
しますbytes
。(.encode()
関数) - デコード:変換
bytes
しますstring
。(.decode()
関数)
:Pythonの3の場合、これは明確であるstring
(ユニコード)のみに符号化することができるbytes
使用はencode()
、Aは、bytes
のみに復号可能なstring
使用(ユニコード)decode()
。呼び出す-あなたはそれを他の方法でラウンドすることができませんdecode
上string
または呼び出しencode
にbytes
あなたにエラーが発生しますが。
Pythonの2が再び多くのメシエで、あなたが呼び出すことができますdecode()
/ decode()
のいずれかでstr
(bytes
)またはunicode
述べたように、他の方法でそれをやってすることはあまり意味がありませんが、。
どちら.encode()
と.decode()
取ることができますencoding
パラメータを、通常はデフォルトのエンコーディングはOKです。しかし、いくつかの状況では、例外が発生することができます。
- (にエンコードする場合
bytes
、指定したエンコードは元の文字列内のコンテンツの一部を表すことができない場合)、(たとえば、あなたは「ASCII」エンコーディングを使用して、いくつかの漢字をエンコードしようとしている)、UnicodeEncodingErrorが発生します。 - (からのデコード時同様、
bytes
)元バイトが与えられたエンコーディングでは不可能(一部の無効なバイトシーケンスが含まれている場合、たとえば、あなたが「UTF-8」を使用して解読しようとするが、元のバイトは行っていないいくつかのシーケンスが含まれている場合任意の有効な「UTF-8」エンコードされたバイト)で表示されるように、UnicodeDecodeErrorが発生します。
オブジェクトがあるかどうかを確認 string
:Pythonの3では、それは簡単ですisinstance(obj, str)
(文字列の唯一のタイプがあるのでstr
ユニコードである、)が、Pythonの2に、あなたがしなければならない:isinstance(obj, basestring)
両方のためであるstr
(bytes
)とunicode
(ユニコード)があると考えられstring
、その親クラスはこれですbasestring
。
ファイルシステムのエンコーディング
これは厳密にはPython固有の問題ではありませんが、あなたも自分の名前が文字化けすることがあり、ファイルを扱う堅牢なプログラムを書きたいならば知識は有用です。そして、この問題はイバラのです。
問題:
-
* nixの、ファイルシステムの基礎となる、パス(ディレクトリ/ファイル)に名前がありません、それとのエンコーディングを持っているので、彼らはただあり
bytes
、予約「/」以外もしくは(バイトの任意のシーケンスを含めることができますnul
私はありません場合は、Linux上で違う)。だから、彼らはに変換するためにstrings
、我々は、Pythonにによって提供されエンコーディング、必要sys.getfilesystemencoding()
(ほとんど常に「UTF-8」)機能を。今、私はあなたがすでに右ここに問題を感じると思いますか?はい、問題は入力以来ということですbytes
任意であり、それは我々が与えられたエンコーディング(文字化け)を使用してそれらをデコードできない可能性があります。2 3 -
Windowsでは、しかし、APIの設計には、Unicodeを使用して、パス名にアクセスする必要がある2
だから、どのように我々はこの問題に取り組むのでしょうか?私は「完全かつ適切な」ソリューションはずっと努力のかもしれないと思うと、ここではちょうど私の意見です。
-
簡単にするために、常にパス名にUnicodeを使用して、あなたがいる限り、ユーザーのコンピュータには文字化けのパス名が存在しないよう、常にWindows上で安全な、と* nixの上安全です。- Pythonの3は、保護のもう一つの層を提供します
surrogateescape encoding error handler
。4 5これはさえ文字化けパス名のために働くかもしれないが、私は試していないし、これについて確認することができません。 -
* nixの上の任意のパス名を処理できるようにするには、その後、使用する必要があります
bytes
私は、文字列をやって頭痛の多くをもたらすだろうと思い、パス名、のためbytes
の変換、およびプログラムは、おそらく上のUnicodeのパス名に100%動作しません。 Windowsの。これは迷惑に聞こえます。
一般的に、あなたは、パス名にUnicodeを使用する必要があります。
エンコード/ロケール関連機能
-
sys.getdefaultencoding()
:
現在のUnicode処理のデフォルトエンコーディング名を返します。
私は(このエンコーディングはUnicodeとバイトの変換に使用されるデフォルトのエンコーディングを参照すると思いますencode()
、decode()
)。Python2では、デフォルトはascii
Pythonの3では、デフォルトであるが、utf-8
。(いつものようにサプライズ)
-
sys.getfilesystemencoding()
:
システムのデフォルトエンコーディングが使用されている場合は、システムのファイル名、またはNoneにUnicodeのファイル名を変換するために使用されるエンコーディングの名前を返します。結果の値は、オペレーティング・システムによって異なります。
- Mac OS Xでは、エンコーディングは 'UTF-8' です。
- nl_langinfo(CODESET)が失敗した場合Unixでは、エンコーディングはにnl_langinfo(CODESET)、又はなしの結果に応じて、ユーザの好みです。
- Windows NT +では、ファイル名はUnicodeをネイティブにしているので、変換は行われません。これは、彼らが明示的にファイル名として使用した場合と同等ですバイト文字列にUnicode文字列を変換したい場合、アプリケーションが使用すべきエンコーディングであるとして)(getfilesystemencodingはまだ、「MBCS」を返します。
- Windowsの9xでは、エンコーディングは 'MBCS' です。
-
locale.getdefaultlocale([envvars])
:
デフォルトロケール設定を決定しようとフォーム(言語コード、エンコーディング)のタプルとしてそれらを返します。
POSIXによると、にsetlocale(LC_ALL、「」)と呼ばれていないプログラムは、C「ロケールポータブルを使用して実行されます」。(LC_ALL、「」)はsetlocaleを呼び出すと、LANG変数で定義されたデフォルトのロケールを使用することができます。我々は現在のロケール設定に干渉したくないので、私たちは、このように、上記の方法で動作をエミュレートします。
他のプラットフォームとの互換性を維持するには、LANG変数がテストされますが、envvarsのパラメータとして与えられた変数のリストされていないだけ。最初に使用される定義されていることが判明します。envvarsのGNU gettextのに使用される検索パスデフォルト。それは、常に変数名LANGが含まれている必要があります。GNU gettextの検索パスは、そのためには、 'LANGUAGE'、 'LC_ALL'、 'LC_CTYPE'、および 'LANG' が含まれています。
コード「C」を除いて、言語コードは、その値が決定できない場合NoneにできるRFC 1766言語コード及び符号化に対応します。
-
locale.getlocale([category])
:
言語コード、エンコーディングを含む配列として指定されたロケールカテゴリの現在の設定を返します。カテゴリはLC_ALLを除くLC_ *値のものであってもよいです。それLC_CTYPEデフォルト。
コード「C」を除いて、言語コードは、その値が決定できない場合NoneにできるRFC 1766言語コード及び符号化に対応します。
-
locale.getpreferredencoding([do_setlocale])
:
一般的に、あなたがすべき避けるため、対応する呼び出しset...
、彼らはあなたのコードだけでなく、影響を与え、システム全体への影響を、持っているように、機能を、しかしパッケージがインポート。
ボーナス点:
- 役立つかもしれない2と3 compitable図書館:https://pythonhosted.org/six/
リファレンス
オリジナル:ビッグボックスは、 PythonでのUnicodeの扱い