web-dev-qa-db-ja.com

Pythonの文字列がASCIIであるかどうかを確認する方法は?

文字列がASCIIにあるかどうかを確認します。

ord()を知っていますが、ord('é')を試してみるとTypeError: ord() expected a character, but string of length 2 foundがあります。 Pythonの作成方法が原因であると理解しました( ord()のドキュメント で説明されています)。

チェックする別の方法はありますか?

183
Nico
def is_ascii(s):
    return all(ord(c) < 128 for c in s)
150

あなたは正しい質問をしていないと思う-

pythonの文字列には、 'ascii'、utf-8、またはその他のエンコーディングに対応するプロパティがありません。文字列のソース(ファイルから読み取るか、キーボードから入力するかなど)は、文字列を生成するためにASCII文字列をUnicode文字列にエンコードしている場合がありますが、答えを見つける必要があります。

おそらくあなたが尋ねることができる質問は:「この文字列はASCII文字列をASCIIでエンコードした結果ですか?」 -これを試して答えることができます:

try:
    mystring.decode('ascii')
except UnicodeDecodeError:
    print "it was not a ascii-encoded unicode string"
else:
    print "It may have been an ascii-encoded unicode string"
241

Python 3の方法:

isascii = lambda s: len(s) == len(s.encode())

チェックするには、テスト文字列を渡します:

str1 = "♥O◘♦♥O◘♦"
str2 = "Python"

print(isascii(str1)) -> will return False
print(isascii(str2)) -> will return True
140
far

最近このようなものに走った-将来の参考のために

import chardet

encoding = chardet.detect(string)
if encoding['encoding'] == 'ascii':
    print 'string is in ascii'

以下で使用できます:

string_ascii = string.decode(encoding['encoding']).encode('ascii')
20
Alvin

Python 3.7の新機能( bpo32677

文字列の面倒な/非効率的なASCIIチェックはもう必要ありません。新しい組み込みstr/bytes/bytearrayメソッド- .isascii() は、文字列がasciiかどうかをチェックします。

print("is this ascii?".isascii())
# True
19
abccd

あなたの質問は間違っています。表示されるエラーは、Pythonのビルド方法の結果ではなく、バイト文字列とUnicode文字列の混乱によるものです。

バイト文字列(python構文の「foo」または「bar」など)は、オクテットのシーケンスです。 0〜255の数字。 Unicode文字列(例:u "foo"またはu'bar ')は、Unicodeコードポイントのシーケンスです。 0〜1112064の数字。しかし、あなたは文字éに興味があるように見えます。これは(端末では)単一の文字を表すマルチバイトシーケンスです。

ord(u'é')の代わりに、これを試してください:

>>> [ord(x) for x in u'é']

これにより、「é」が表すコードポイントのシーケンスがわかります。それはあなたに与えるかもしれない[233]、またはあなたに与えるかもしれない[101、770]。

これを逆にするchr()の代わりに、unichr()があります:

>>> unichr(233)
u'\xe9'

この文字は実際には、単一または複数のユニコード「コードポイント」のいずれかで表される場合があり、それ自体が書記素または文字のいずれかを表します。 「鋭アクセント付きe(コードポイント233)」または「e」(コードポイント101)の後に「前の文字の鋭アクセント」(コードポイント770)が続きます。したがって、このまったく同じ文字がPythonデータ構造体u'e\u0301'またはu'\u00e9'として表示される場合があります。

ほとんどの場合、これを気にする必要はありませんが、Unicode文字列を反復処理している場合は、分解可能な文字ではなくコードポイントによって反復処理が行われるため、問題になる可能性があります。つまり、len(u'e\u0301') == 2およびlen(u'\u00e9') == 1です。これが問題になる場合は、 unicodedata.normalize を使用して、合成形式と分解形式を変換できます。

The Unicode Glossary は、各特定の用語がテキスト表現の異なる部分をどのように参照するかを指摘することにより、これらの問題のいくつかを理解するための有用なガイドとなります。

17
Glyph

これはどうですか?

import string

def isAscii(s):
    for c in s:
        if c not in string.ascii_letters:
            return False
    return True
10
miya

Vincent Marchettiには正しい考えがありますが、str.decodeはPython 3で非推奨になりました。Python 3では、str.encodeで同じテストを行うことができます。

try:
    mystring.encode('ascii')
except UnicodeEncodeError:
    pass  # string is not ascii
else:
    pass  # string is ascii

キャッチする例外もUnicodeDecodeErrorからUnicodeEncodeErrorに変更されていることに注意してください。

10
drs

エンコードがわからない文字列の使用/エンコード/デコードの方法(およびその文字列の特殊文字をエスケープ/変換する方法)を決定しようとしたときにこの質問を見つけました。

私の最初のステップは、文字列のタイプをチェックすることだったはずです-私はそこから、そのフォーマットに関する良いデータをタイプから取得できることに気づきませんでした。 この回答は非常に役に立ち、私の問題の本当の根本に到達しました。

失礼で執persistentになったら

UnicodeDecodeError: 'ascii'コーデックは、位置263のバイト0xc3をデコードできません:順序が範囲外(128)

特にエンコードするときは、すでにIS unicodeである文字列をunicode()しようとしていないことを確認してください。何らかの恐ろしい理由で、ASCIIコーデックエラーが発生します。 (これがどれほどひどいものであるかについてのより良い理解のために Python KitchenレシピPython docs チュートリアルも参照してください。)

最終的に私がやりたいことはこれだと判断しました:

escaped_string = unicode(original_string.encode('ascii','xmlcharrefreplace'))

また、デバッグに役立つのは、私のファイルのデフォルトコーディングをutf-8に設定することです(これをpythonファイルの先頭に配置します)。

# -*- coding: utf-8 -*-

これにより、ユニコードエスケープ(u '\ xe0\xe9\xe7')を使用せずに特殊文字( 'àéç')をテストできます。

>>> specials='àéç'
>>> specials.decode('latin-1').encode('ascii','xmlcharrefreplace')
'&#224;&#233;&#231;'
9
Max P Magee

Python 2.6(およびPython 3.x)からAlexanderのソリューションを改善するには、ヘルパーモジュールcurses.asciiを使用し、curses.ascii.isascii()関数またはその他のさまざまなものを使用できます。 https://docs.python.org/2.6/library/curses.ascii.html

from curses import ascii

def isascii(s):
    return all(ascii.isascii(c) for c in s)

Posix標準[[:ASCII:]]定義を受け入れる正規表現ライブラリを使用できます。

2
Steve Moyer

Pythonの文字列(str- type)は一連のバイトです。 方法はありませんこの一連のバイトがASCII文字列、ISO-8859-1のような8ビット文字セットの文字列、またはUTF-でエンコードされた文字列を表すかどうかを文字列を見ただけで判断します8またはUTF-16または何でも。

ただし、使用されているエンコーディングがわかっている場合は、decode strをUnicode文字列に入れてから、正規表現(またはループ)を使用して、対象範囲外の文字が含まれているかどうかを確認できます。

2
JacquesB

@RogerDahlの answer と同様ですが、文字クラスを無効にし、find_allまたはmatchの代わりに検索を使用することで、より効率的に短絡できます。

>>> import re
>>> re.search('[^\x00-\x7F]', 'Did you catch that \x00?') is not None
False
>>> re.search('[^\x00-\x7F]', 'Did you catch that \xFF?') is not None
True

このために正規表現が最適化されていると思います。

0
hobs
import re

def is_ascii(s):
    return bool(re.match(r'[\x00-\x7F]+$', s))

空の文字列をASCIIとして含めるには、+*に変更します。

0
Roger Dahl

コードがクラッシュしないようにするには、try-exceptを使用してTypeErrorsをキャッチすることもできます

>>> ord("¶")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: ord() expected a character, but string of length 2 found

例えば

def is_ascii(s):
    try:
        return all(ord(c) < 128 for c in s)
    except TypeError:
        return False
0
user2489252