文字列がUnicodeまたはASCIIかどうかを確認するにはどうすればよいですか?


271

文字列のエンコーディングを把握するには、Pythonで何をする必要がありますか?


56
Unicodeはエンコーディングではありません
ulidtko

さらに重要なことに、なぜあなたは気にする必要がありますか?
Johnsyweb

@Johnsywebための{UnicodeDecodeError} 'ascii' codec can't decode byte 0xc2
アレックス・

回答:


295

Python 3では、すべての文字列はUnicode文字のシーケンスです。bytes生のバイトを保持するタイプがあります。

Python 2では、文字列はtype strまたはTypeの場合があり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範囲の純粋な文字で構成される場合があり、バイト文字列は、ASCII、エンコードされたUnicode、または非テキストデータを含む場合があります。


3
@ProsperousHeart:あなたはおそらく、Pythonの3を使用している
グレッグHewgill

124

オブジェクトが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では、strPython 2と同様にunicode、テキストを格納するために使用されます。何と呼ばれていたstrのPython 2には、呼び出されたbytesPythonの3に。


バイト文字列が有効な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)

他の人の参照のためだけに-str.decodeはpython 3には存在しません。unicode(s, "ascii")何かしなければならないようです
Shadow

3
申し訳ありませんが、私は意味したstr(s, "ascii")
シャドウ

1
これはpython 3では正確ではありません
ProsperousHeart

2
@ProsperousHeart Python 3をカバーするように更新されました。また、バイト文字列とUnicode文字列の違いを説明しようとしました。
ミケル

44

Python 3.xでは、すべての文字列はUnicode文字のシーケンスです。また、str(デフォルトではUnicode文字列を意味します)のisinstanceチェックを実行するだけで十分です。

isinstance(x, str)

Python 2.xに関しては、ほとんどの人が2つのチェックを持つifステートメントを使用しているようです。1つはstr用、もう1つはUnicode用です。

「string-like」オブジェクトがあるかどうかをすべて1つのステートメントで確認したい場合は、次のようにします。

isinstance(x, basestring)

これは誤りです。Python 2.7ではisinstance(u"x",basestring)が返されますTrue
PythonNut 2014年

11
@PythonNut:それがポイントだったと思います。isinstance(x、basestring)の使用は、上記の個別の二重テストを置き換えるのに十分です。
KQ。

5
これは多くの場合に役立ちますが、質問者が何を意味していたかは明らかではありません。
mhsmith

3
これが質問への答えです。他のすべての人は、OPの発言を誤解し、Pythonでの型チェックに関する一般的な答えを出しました。
fiatjaf 2015

1
OPの質問には答えません。質問のタイトル(単独)は、この答えが正しいように解釈できます。ただし、OPは質問の説明で「どちらを図化するか」を明確に述べており、この回答ではそれについては触れていません。
MD004 2018年

31

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

ASCII、UTF-8、およびその他のバイト文字列が「テキスト」の場合...

...そしてUnicodeは「テキストらしさ」です。

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

McMillanのUnicode In Python、 PyCon 2008の完全に謎解きの講演を読んで、Stack Overflowの関連するほとんどの回答よりもはるかに優れた点について説明しています。


これらのスライドは、Unicode Iへの最良の導入は、これまでに渡って来て、おそらくある
ジョニー

23

あなたのコードのニーズはと互換性のある場合は、両方のPython 2とPython 3、あなたは直接のようなものを使用することはできませんisinstance(s,bytes)やがisinstance(s,unicode)あるため、以外やPythonのバージョンのテスト/どちらかの試みでそれらをラップすることなく、bytesPythonの2に定義されていないとunicodeのPython 3で定義されていません。

いくつかの醜い回避策があります。非常に醜いのは、型自体を比較するのではなく、型の名前を比較することです。次に例を示します。

# 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)

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


6
より良い方法は、おそらく使用されsix、そしてテストに対するsix.binary_typesix.text_type
イアンClelland

1
type(s).__ name__を使用して、タイプ名をプローブできます。
Paulo Freitas 2013

論理エラーがない限り、そのコードのユースケースはよくわかりません。Python 2のコードには「not」があるはずだと思います。それ以外の場合は、すべてをPython 3ではUnicode文字列に変換し、Python 2では逆にします!
オリゴフレン2014年

はい、オリゴフレン、それはそれがすることです。標準の内部文字列は、Python 3ではUnicode、Python 2ではASCIIです。そのため、コードスニペットはテキストを標準の内部文字列タイプ(UnicodeまたはASCII)に変換します。
Dave Burton

12

使用する:

import six
if isinstance(obj, six.text_type)

6つのライブラリ内では、次のように表されます。

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

2
それはあるはずですif isinstance(obj, six.text_type) 。しかし、これは正しい答えです。
カランタン

OPの質問には答えません。質問のタイトル(単独)は、この答えが正しいように解釈できます。ただし、OPは質問の説明で「どちらを図化するか」を明確に述べており、この回答ではそれについては触れていません。
MD004 2018年

4

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

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


3

これは他の人に役立つかもしれません。変数sの文字列型のテストを開始しましたが、私のアプリケーションでは、単にsをutf-8として返す方が理にかなっています。次に、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

あなたは私の友人が正解するに値する!私はpython 3を使用していますが、この宝物が見つかるまで問題が解決しませんでした。
mnsr

2

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



0

簡単な方法の1つunicodeは、組み込み関数かどうかを確認することです。もしそうなら、あなたはPython 2にいて、あなたの文字列は文字列になります。すべてがunicode1つにあることを確認するには:

import builtins

i = 'cats'
if 'unicode' in dir(builtins):     # True in python 2, False in 3
  i = unicode(i)
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.