文字列がどのエンコーディングであるかを理解するためにPythonで何をしなければなりませんか?
Python 3では、すべての文字列はUnicode文字のシーケンスです。生のバイトを保持するbytes
型があります。
Python 2では、文字列はstr
型またはunicode
型になります。次のようなコードを使用してどれがわかります。
def whatisthis(s):
if isinstance(s, str):
print "ordinary string"
Elif isinstance(s, unicode):
print "unicode string"
else:
print "not a string"
これは「UnicodeまたはASCII」を区別しません。それはPythonの型を区別するだけです。 Unicode文字列はASCIIの範囲内の純粋な文字で構成され、bytes文字列はASCII、エンコードされたUnicode、さらには非テキストデータさえも含みます。
type
またはisinstance
を使用できます。
Python 2では:
>>> type(u'abc') # Python 2 unicode string literal
<type 'unicode'>
>>> type('abc') # Python 2 byte string literal
<type 'str'>
Python 2では、str
は単なるバイト列です。 Pythonはそのエンコーディングが何であるかを知りません。 unicode
型はテキストを保存するためのより安全な方法です。もっと理解したいのなら、 http://farmdev.com/talks/unicode/ をお勧めします。
Python 3では:
>>> type('abc') # Python 3 unicode string literal
<class 'str'>
>>> type(b'abc') # Python 3 byte string literal
<class 'bytes'>
Python 3では、str
はPython 2のunicode
と似ており、テキストを格納するために使用されます。 Python 2ではstr
と呼ばれていたものは、Python 3ではbytes
と呼ばれています。
decode
を呼び出すことができます。 UnicodeDecodeError例外が発生した場合、それは無効でした。
>>> u_umlaut = b'\xc3\x9c' # UTF-8 representation of the letter 'Ü'
>>> u_umlaut.decode('utf-8')
u'\xdc'
>>> u_umlaut.decode('ascii')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
UnicodeDecodeError: 'ascii' codec can't decode byte 0xc3 in position 0: ordinal not in range(128)
Python 3.xではすべての文字列はUnicode文字のシーケンスです。また、strのisinstanceチェック(デフォルトではUnicode文字列を意味します)を実行すれば十分です。
isinstance(x, str)
Python 2.xに関して、ほとんどの人は2つのチェックを持つif文を使っているようです。 1つはstr用、もう1つはunicode用です。
1つのステートメントで 'string-like'オブジェクトがすべて揃っているかどうかを確認したい場合は、次のようにします。
isinstance(x, basestring)
Unicodeはエンコーディングではありません - Kumar McMillanを引用すると、
ASCII、UTF-8、およびその他のバイト文字列が "text"の場合...
... Unicodeは「テキスト性」です。
それはテキストの抽象的な形です
PythonでMcMillanの Unicodeを読んでください。PyCon2008のCompletely Demystified の講演で、Stack Overflowに関するほとんどの関連する答えよりもはるかに良いことが説明されています。
あなたのコードがPython 2とPython 3の両方と互換性がある必要がある場合は、isinstance(s,bytes)
やisinstance(s,unicode)
のようなものを直接試すことはできません。 Python 2ではbytes
は未定義であり、Python 3ではunicode
は未定義であるためです。
いくつかの醜い回避策があります。非常に醜いのは、型そのものを比較するのではなく、型の名前を比較することです。これが例です:
# convert bytes (python 3) or unicode (python 2) to str
if str(type(s)) == "<class 'bytes'>":
# only possible in Python 3
s = s.decode('ascii') # or s = str(s)[2:-1]
Elif str(type(s)) == "<type 'unicode'>":
# only possible in Python 2
s = str(s)
間違いなくやや醜い回避策は、Pythonのバージョン番号をチェックすることです。
if sys.version_info >= (3,0,0):
# for Python 3
if isinstance(s, bytes):
s = s.decode('ascii') # or s = str(s)[2:-1]
else:
# for Python 2
if isinstance(s, unicode):
s = str(s)
これらはどちらも非公開であり、ほとんどの場合、おそらくもっと良い方法があります。
つかいます:
import six
if isinstance(obj, six.text_type)
6つのライブラリの中では、
if PY3:
string_types = str,
else:
string_types = basestring,
Python 3では、次のいずれかを言うのはそれほど公平ではないことに注意してください。
str
sは任意のxに対してUTFxです(例:UTF8)
str
sはUnicodeです
str
sはUnicode文字の順序付きコレクションです
Pythonのstr
型は(通常)一連のUnicodeコードポイントです。その一部は文字にマッピングされます。
Python 3でも、この質問に答えるのは想像以上に簡単ではありません。
ASCII互換の文字列をテストするための明白な方法は試みられたエンコードによるものです:
"Hello there!".encode("ascii")
#>>> b'Hello there!'
"Hello there... ☃!".encode("ascii")
#>>> Traceback (most recent call last):
#>>> File "", line 4, in <module>
#>>> UnicodeEncodeError: 'ascii' codec can't encode character '\u2603' in position 15: ordinal not in range(128)
エラーはケースを区別します。
Python 3には、無効なUnicodeコードポイントを含む文字列もいくつかあります。
"Hello there!".encode("utf8")
#>>> b'Hello there!'
"\udcc3".encode("utf8")
#>>> Traceback (most recent call last):
#>>> File "", line 19, in <module>
#>>> UnicodeEncodeError: 'utf-8' codec can't encode character '\udcc3' in position 0: surrogates not allowed
それらを区別するために同じ方法が使用されます。
これは他の誰かに役立つかもしれません、私は変数の文字列型のテストを始めました、しかし私のアプリケーションのために、それは単にutf-8としてsを返す方が理にかなっていました。 return_utfを呼び出すプロセスは、それが何を処理しているのかを知っており、文字列を適切に処理できます。コードは手付かずのものではありませんが、バージョンテストや6をインポートせずにPythonバージョンに依存しないようにするつもりです。他の人を助けるために、以下のサンプルコードの改善点についてコメントしてください。
def return_utf(s):
if isinstance(s, str):
return s.encode('utf-8')
if isinstance(s, (int, float, complex)):
return str(s).encode('utf-8')
try:
return s.encode('utf-8')
except TypeError:
try:
return str(s).encode('utf-8')
except AttributeError:
return s
except AttributeError:
return s
return s # assume it was already utf-8
Universal Encoding Detector を使用することもできますが、実際のエンコーディングではなく、単に推測できるだけであることに注意してください。たとえば、文字列 "abc"です。他の場所でエンコーディング情報を取得する必要があります。例えば、HTTPプロトコルはそのためにContent-Typeヘッダを使用します。
Py2/py3互換性のためには単に使う
import six if isinstance(obj, six.text_type)