Python 2.6で実行しているコードベースをすでに取得しています。Python 3.0を準備するために、以下を追加しました。
__future__からインポートunicode_literals
私たちの.py
ファイルに(私たちがそれらを変更するにつれて)。他の誰かがこれを行っていて、(おそらくデバッグに多くの時間を費やした後で)明らかでない落とし穴に遭遇したのではないかと思います。
Python 2.6で実行しているコードベースをすでに取得しています。Python 3.0を準備するために、以下を追加しました。
__future__からインポートunicode_literals
私たちの.py
ファイルに(私たちがそれらを変更するにつれて)。他の誰かがこれを行っていて、(おそらくデバッグに多くの時間を費やした後で)明らかでない落とし穴に遭遇したのではないかと思います。
回答:
ユニコード文字列で作業してきた問題の主な原因は、UTF-8でエンコードされた文字列とユニコード文字列を混在させることです。
たとえば、次のスクリプトについて考えてみます。
two.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
runningの出力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'
はUnicode文字列であり、Pythonがデコードしようとするため失敗しますhtml
。印刷を修正する方法はいくつかのどちらかやっているのprint str('DEBUG: %s') % html
かprint 'DEBUG: %s' % html.decode('utf-8')
。
これが、ユニコード文字列を使用する際の潜在的な問題を理解するのに役立つことを願っています。
when you mix utf-8 encoded strings with unicode ones
UTF-8とUnicodeは2つの異なるエンコーディングではありません。Unicodeは標準であり、UTF-8はそれが定義するエンコーディングの1つです。
str
、後者はタイプunicode
です。異なるオブジェクトであるため、それらを合計/連結/補間しようとすると問題が発生する可能性があります
python>=2.6
またはに適用されますかpython==2.6
?
また、2.6(python 2.6.5 RC1 +より前)では、Unicodeリテラルがキーワード引数でうまく機能しません(issue4978):
たとえば、次のコードはunicode_literalsがなくても機能しますが、TypeErrorで失敗しますkeywords must be string
。unicode_literalsが使用されている場合。
>>> 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
unicode_literals
ディレクティブを追加する場合は、次のようなものも追加する必要があることがわかりました。
# -*- coding: utf-8
.pyファイルの1行目または2行目に。そうでなければ次のような行:
foo = "barré"
次のようなエラーが発生します。
SyntaxError:ファイルmumble.pyの198行目の非ASCII文字 '\ xc3'、 しかし、宣言されたエンコーディングはありません。http://www.python.org/peps/pep-0263.htmlを参照してください 詳細については
# -*- coding: utf-8
は、使用するunicode_literals
かしないかにかかわらず、実質的に必須のステートメントです
-*-
必要とされていません。emacs互換の方法を使用している場合は、必要になると思います-*- encoding: utf-8 -*-
(-*-
最後のも参照してください)。必要なのはcoding: utf-8
(またはの=
代わりに:
)だけです。
from __future__ import unicode_literals
。
# -*- coding: utf-8 -*-
「コーディング」が必要です(「エンコーディング」や「ファイルエンコーディング」などではありません。Pythonは接頭辞に関係なく「コーディング」を探します)。
また、unicode_literal
影響を与えるeval()
が影響を与えないことも考慮に入れてくださいrepr()
(非対称の動作であり、これはバグです)。つまりeval(repr(b'\xa4'))
、b'\xa4'
(Python 3の場合のように)等しくありません。
理想的には、次のコードは不変であり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'
ます。
repr
、オブジェクトの再生成に使用していることだと思います。repr
ドキュメントは明確であると述べていない要件。私の意見では、これrepr
はデバッグにのみ役立つものに依存しています。
もっとあります。
ユニコードを許容しない文字列を期待するライブラリとビルトインがあります。
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()(私のもの)への呼び出しでいっぱいである場合、後者は壊滅的です。
やった、えっ?!?
class Meta:
は次のようになりますb'field_name'
Clickは、from __future__ import unicode_literals
使用しているモジュールがインポートされている場合、Unicode例外を発生させますclick.echo
。それは悪夢です…
decode()
代わりの解決策str()
やencode()
解決策:より頻繁にあなたがUnicodeオブジェクトを使用して、何がしたいことは、外部暗黙のエンコードで文字、ないバイトの配列の文字列を操作することであるため、明確なコードは、あります。