ホームページ > バックエンド開発 > Python チュートリアル > Python Unicode 文字列フォーマットの落とし穴

Python Unicode 文字列フォーマットの落とし穴

大家讲道理
リリース: 2016-11-07 10:14:00
オリジナル
1431 人が閲覧しました

今日、同僚の不可解な UnicodeDecodeError の調査を手伝っていたときに、Python の文字列フォーマットに小さなトラップがあることを発見しました。ここに記録します。元のコードは複雑すぎて、問題に関係のないものが多すぎたので、ipython での簡単なテストを通じて問題を再現しました。プロセスは次のとおりです:

In [4]: a = '你好世界'
In [5]: print 'Say this: %s' % a
Say this: 你好世界
In [6]: print 'Say this: %s and say that: %s' % (a, 'hello world')
Say this: 你好世界 and say that: hello world
In [7]: print 'Say this: %s and say that: %s' % (a, u'hello world')
---------------------------------------------------------------------------
UnicodeDecodeError                        Traceback (most recent call last)
/home/jerry/ in ()
UnicodeDecodeError: 'ascii' codec can't decode byte 0xe4 in position 10: ordinal not in range(128)
In [8]: a
Out[8]: '\xe4\xbd\xa0\xe5\xa5\xbd\xe4\xb8\x96\xe7\x95\x8c'
ログイン後にコピー

In [7] の後に奇妙な UnicodeDecodeError が表示されたことがありますか?前の文との唯一の違いは、「hello world」が str オブジェクトではなく unicode オブジェクトになることです。しかし問題は、「hello world」は ASCII 以外の文字を含まない単純な英語の文字列であるということです。これをデコードできないのはなぜでしょうか。例外に添付されたメッセージをよく見てください。これは明らかに「hello world」ではないので、[8] で出力された中国語の文を疑うしかありません。それはともかく、最初のものは 0xe4 です。

Python は文字列をフォーマットするときに を Unicode オブジェクトにデコードしようとし、デコードするときに実際の UTF-8 エンコードではなくデフォルトの ASCII エンコードが使用されるようです。どうしたの? ?実験を続けましょう:

In [9]: 'Say this: %s' % 'hello'
Out[9]: 'Say this: hello'
In [10]: 'Say this: %s' % u'hello'
Out[10]: u'Say this: hello'
ログイン後にコピー

よく見てください、In [9] の 'hello' は通常の文字列であり、結果も文字列 (str オブジェクト) ですが、In [10] の 'hello' は unicode オブジェクトになります。フォーマットされた結果も Unicode になります (結果の先頭にある u に注意してください)。

真実は次のとおりです: Python には文字列をフォーマットするときにいくつかの隠されたトリックがあります。%s に対応するパラメーターに Unicode がある場合、最終結果も Unicode になります。この場合、%s パラメータ内のテンプレート文字列とすべての str は Unicode にデコードされますが、このデコードは暗黙的であり、Python が使用できる文字セットはデフォルトの ASCII のみを使用できます。その中に非 ASCII エンコード文字列が含まれている場合は、それで終わりです...

Python ドキュメントの内容を見てください:

If format is a Unicode object, or if any of the objects being converted using the %s conversion are Unicode objects, the result will also be a Unicode object.
ログイン後にコピー

コード内に str と unicode が混在している場合、この種の問題が簡単に発生する可能性があります。私の同僚のコードでは、中国語の文字列はユーザ​​ーによって入力され、正しくエンコードされています。これは UTF-8 でエンコードされた str オブジェクトですが、その内容はすべて ASCII コードですが、そのソースは次のとおりです。 sqlite3 データベース クエリと sqlite API によって返される文字列はすべて Unicode オブジェクトであるため、このような奇妙な結果が生じます。

Python 2 の str と unicode は本当に不正行為であり、私はそれらによって何度か被害を受けました。 Python 3 はこの点で大幅な改善を行っており、完全に普及することを期待しています。


ソース:php.cn
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート