web-dev-qa-db-ja.com

文字列がUnicodeかASCIIかどうかをどうやって確認するのですか?

文字列がどのエンコーディングであるかを理解するためにPythonで何をしなければなりませんか?

241
TIMEX

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、さらには非テキストデータさえも含みます。

265
Greg Hewgill

オブジェクトが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と呼ばれています。


バイト文字列が有効かどうかを調べる方法utf-8またはascii

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)
107
Mikel

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)
43
ThinkBonobo

Unicodeはエンコーディングではありません - Kumar McMillanを引用すると、

ASCII、UTF-8、およびその他のバイト文字列が "text"の場合...

... Unicodeは「テキスト性」です。

それはテキストの抽象的な形です

PythonでMcMillanの Unicodeを読んでください。PyCon2008のCompletely Demystified の講演で、Stack Overflowに関するほとんどの関連する答えよりもはるかに良いことが説明されています。

31
Alex Dean

あなたのコードが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)

これらはどちらも非公開であり、ほとんどの場合、おそらくもっと良い方法があります。

22
Dave Burton

つかいます:

import six
if isinstance(obj, six.text_type)

6つのライブラリの中では、

if PY3:
    string_types = str,
else:
    string_types = basestring,
9
madjardi

Python 3では、次のいずれかを言うのはそれほど公平ではないことに注意してください。

  • strsは任意のxに対してUTFxです(例:UTF8)

  • strsはUnicodeです

  • strsは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

それらを区別するために同じ方法が使用されます。

4
Veedrac

これは他の誰かに役立つかもしれません、私は変数の文字列型のテストを始めました、しかし私のアプリケーションのために、それは単に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
2
jfl

Universal Encoding Detector を使用することもできますが、実際のエンコーディングではなく、単に推測できるだけであることに注意してください。たとえば、文字列 "abc"です。他の場所でエンコーディング情報を取得する必要があります。例えば、HTTPプロトコルはそのためにContent-Typeヘッダを使用します。

2
Seb

Py2/py3互換性のためには単に使う

import six if isinstance(obj, six.text_type)

0