101

Python 2.6 で動作するコード ベースを既に取得しています。Python 3.0 に備えるために、以下の追加を開始しました。

from __future__ import unicode_literals

私たちの.pyファイルに(私たちがそれらを変更するにつれて)。他の誰かがこれを行っていて、明らかでない落とし穴に遭遇したかどうか疑問に思っています (おそらくデバッグに多くの時間を費やした後)。

4

6 に答える 6

101

私がユニコード文字列を扱う際に発生した問題の主な原因は、utf-8 でエンコードされた文字列とユニコード文字列を混在させた場合です。

たとえば、次のスクリプトを考えてみましょう。

2.py

# encoding: utf-8
name = 'helló wörld from two'

one.py

# encoding: utf-8
from __future__ import unicode_literals
import two
name = 'helló wörld from one'
print name + two.name

実行の出力python one.pyは次のとおりです。

Traceback (most recent call last):
  File "one.py", line 5, in <module>
    print name + two.name
UnicodeDecodeError: 'ascii' codec can't decode byte 0xc3 in position 4: ordinal not in range(128)

この例でtwo.nameは、 は をインポートしていないため、utf-8 でエンコードされた文字列 (Unicode ではない)unicode_literalsであり、one.nameは Unicode 文字列です。両方を混在させると、python はエンコードされた文字列 (ASCII であると仮定) をデコードし、それを Unicode に変換しようとして失敗します。そうすればうまくいくでしょうprint name + two.name.decode('utf-8')

文字列をエンコードして後で混合しようとすると、同じことが起こる可能性があります。たとえば、これは機能します:

# encoding: utf-8
html = '<html><body>helló wörld</body></html>'
if isinstance(html, unicode):
    html = html.encode('utf-8')
print 'DEBUG: %s' % html

出力:

DEBUG: <html><body>helló wörld</body></html>

しかし、追加した後はimport unicode_literalsそうではありません:

# encoding: utf-8
from __future__ import unicode_literals
html = '<html><body>helló wörld</body></html>'
if isinstance(html, unicode):
    html = html.encode('utf-8')
print 'DEBUG: %s' % html

出力:

Traceback (most recent call last):
  File "test.py", line 6, in <module>
    print 'DEBUG: %s' % html
UnicodeDecodeError: 'ascii' codec can't decode byte 0xc3 in position 16: ordinal not in range(128)

'DEBUG: %s'はユニコード文字列であるため失敗し、したがって python は をデコードしようとしhtmlます。印刷を修正する方法はいくつかありprint str('DEBUG: %s') % htmlますprint 'DEBUG: %s' % html.decode('utf-8')

これが、Unicode 文字列を使用する際の潜在的な落とし穴を理解するのに役立つことを願っています。

于 2009-05-05T23:52:06.657 に答える
16

また、2.6 (python 2.6.5 RC1+ より前) では、Unicode リテラルはキーワード引数で適切に機能しません ( issue4978 ):

たとえば、次のコードは unicode_literals なしで機能しますが、keywords must be stringUnicode_literals が使用されている場合は TypeError: で失敗します。

  >>> def foo(a=None): pass
  ...
  >>> foo(**{'a':1})
  Traceback (most recent call last):
    File "<stdin>", line 1, in <module>
      TypeError: foo() keywords must be strings
于 2009-11-24T10:10:01.817 に答える
13

unicode_literalsディレクティブを追加する場合は、次のようなものも追加する必要があることがわかりました。

 # -*- coding: utf-8

.pyファイルの1行目または2行目に。それ以外の場合、次のような行:

 foo = "barré"

次のようなエラーが発生します。

SyntaxError:198行目のファイルmumble.pyの非ASCII文字'\ xc3'、
 ただし、エンコーディングは宣言されていません。http://www.python.org/peps/pep-0263.htmlを参照してください
 詳細については
于 2009-05-05T20:09:56.817 に答える
7

unicode_literalまた、影響はあるが影響は受けeval()ないrepr()(imhoがバグである非対称の動作)、つまり(Python 3の場合のように)eval(repr(b'\xa4'))等しくないことも考慮に入れてください。b'\xa4'

unicode_literals理想的には、次のコードは不変であり、Python {2.7、3.x}の使用法のすべての組み合わせに対して常に機能するはずです。

from __future__ import unicode_literals

bstr = b'\xa4'
assert eval(repr(bstr)) == bstr # fails in Python 2.7, holds in 3.1+

ustr = '\xa4'
assert eval(repr(ustr)) == ustr # holds in Python 2.7 and 3.1+

Python 2.7でrepr('\xa4')評価されるため、2番目のアサーションはたまたま機能します。u'\xa4'

于 2010-10-21T11:51:19.223 に答える
5

もっとあります。

Unicode を許容しない文字列を想定するライブラリとビルトインがあります。

2 つの例:

組み込み:

myenum = type('Enum', (), enum)

(少し難解ですが) unicode_literals では動作しません: type() は文字列を想定しています。

図書館:

from wx.lib.pubsub import pub
pub.sendMessage("LOG MESSAGE", msg="no go for unicode literals")

動作しません: wx pubsub ライブラリは文字列メッセージ タイプを想定しています。

前者は難解で、簡単に修正できます

myenum = type(b'Enum', (), enum)

ただし、コードが pub.sendMessage() への呼び出しでいっぱいである場合、後者は壊滅的です(これは私のものです)。

ぶっちゃけ、えっ?!?

于 2013-09-18T12:48:43.330 に答える