文字列がASCIIであるかどうかを確認したい。
私は知っていますord()
、しかし、私が試みるときord('é')
、私は持っていTypeError: ord() expected a character, but string of length 2 found
ます。私はそれが私がPythonを構築した方法によって引き起こされていることを理解しました(ord()
のドキュメントで説明されているように)。
確認する別の方法はありますか?
文字列がASCIIであるかどうかを確認したい。
私は知っていますord()
、しかし、私が試みるときord('é')
、私は持っていTypeError: ord() expected a character, but string of length 2 found
ます。私はそれが私がPythonを構築した方法によって引き起こされていることを理解しました(ord()
のドキュメントで説明されているように)。
確認する別の方法はありますか?
私はあなたが正しい質問をしていないと思います-
Pythonの文字列には、「ascii」、utf-8、またはその他のエンコーディングに対応するプロパティはありません。文字列のソース(ファイルから読み取るか、キーボードから入力するかなど)は、文字列を生成するためにASCIIでUnicode文字列をエンコードしている可能性がありますが、ここで答えを探す必要があります。
おそらく、あなたが尋ねることができる質問は、「この文字列は、ASCIIでUnicode文字列をエンコードした結果ですか?」です。-これはあなたが試すことによって答えることができます:
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"
def is_ascii(s):
return all(ord(c) < 128 for c in s)
Python 3 では、文字列を UTF-8 としてエンコードし、長さが同じかどうかを確認できます。その場合、元の文字列は ASCII です。
def isascii(s):
"""Check if the characters in string s are in ASCII, U+0-U+7F."""
return len(s) == len(s.encode())
確認するには、テスト文字列を渡します。
>>> isascii("♥O◘♦♥O◘♦")
False
>>> isascii("Python")
True
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
。
あなたの質問は間違っています。表示されるエラーは、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'
この文字は、実際には 1 つまたは複数の Unicode の「コード ポイント」で表すことができ、それ自体が書記素または文字を表します。それは、「アキュート アクセント付きの e (つまり、コード ポイント 233)」、または「e」 (コード ポイント 101) の後に「前の文字のアキュート アクセント」 (コード ポイント 770) が続きます。したがって、このまったく同じ文字が Python データ構造u'e\u0301'
またはu'\u00e9'
.
ほとんどの場合、これを気にする必要はありませんが、Unicode 文字列を反復処理する場合、反復は分解可能な文字ではなくコード ポイントで機能するため、問題になる可能性があります。つまり、len(u'e\u0301') == 2
とlen(u'\u00e9') == 1
. これが重要な場合は、 を使用して合成フォームと分解フォームを変換できますunicodedata.normalize
。
Unicode Glossaryは、多くのプログラマーが認識しているよりもはるかに複雑なテキスト表現の異なる部分を特定の用語がどのように参照しているかを指摘することで、これらの問題のいくつかを理解するための役立つガイドとなります。
最近、このようなことに遭遇しました-将来の参考のために
import chardet
encoding = chardet.detect(string)
if encoding['encoding'] == 'ascii':
print 'string is in ascii'
あなたが使用できる:
string_ascii = string.decode(encoding['encoding']).encode('ascii')
エンコードが不明な文字列を使用/エンコード/デコードする方法(およびその文字列内の特殊文字をエスケープ/変換する方法)を決定しようとしたときに、この質問を見つけました。
私の最初のステップは、文字列の型をチェックすることでした。そこで、型からそのフォーマットに関する適切なデータを取得できることに気づいていませんでした。 この答えは非常に役に立ち、私の問題の本当の根源に到達しました。
失礼で執拗になっている場合
UnicodeDecodeError:'ascii'コーデックは位置263のバイト0xc3をデコードできません:序数が範囲(128)にありません
特にエンコードしているときは、すでにユニコードになっている文字列をユニコード()しようとしていないことを確認してください。何らかのひどい理由で、ASCIIコーデックエラーが発生します。(これがどれほどひどいものになるかをよりよく理解するには、 PythonキッチンのレシピとPythonドキュメントのチュートリアルも参照してください。)
最終的に、私がやりたいことはこれだと判断しました。
escaped_string = unicode(original_string.encode('ascii','xmlcharrefreplace'))
また、デバッグに役立つのは、ファイルのデフォルトのコーディングをutf-8に設定することでした(これをPythonファイルの先頭に配置します)。
# -*- coding: utf-8 -*-
これにより、Unicodeエスケープ(u'\ xe0 \ xe9 \ xe7')を使用せずに、特殊文字('àéç')をテストできます。
>>> specials='àéç'
>>> specials.decode('latin-1').encode('ascii','xmlcharrefreplace')
'àéç'
これを行うのはどうですか?
import string
def isAscii(s):
for c in s:
if c not in string.ascii_letters:
return False
return True
Posix標準の[[:ASCII:]]定義を受け入れる正規表現ライブラリを使用できます。
Python の文字列( str
-type) は、一連のバイトです。文字列を見るだけでは、この一連のバイトが ASCII 文字列、ISO-8859-1 のような 8 ビット文字セットの文字列、または UTF-8 や UTF-16 などでエンコードされた文字列を表しているかどうかを判断する方法はありません。 .
ただし、使用されているエンコーディングがわかっている場合はdecode
、str を Unicode 文字列に変換し、正規表現 (またはループ) を使用して、懸念している範囲外の文字が含まれているかどうかを確認できます。
@RogerDahlの回答find_all
と同様ですが、文字クラスを否定し、 orの代わりに検索を使用して短絡する方が効率的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
これには正規表現が最適化されていると思います。
コードがクラッシュするのを防ぐために、 a を使用し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
以下を使用して、文字列が ascii か unicode かを判断します。
>> print 'test string'.__class__.__name__
str
>>> print u'test string'.__class__.__name__
unicode
>>>
次に、条件付きブロックを使用して関数を定義します。
def is_ascii(input):
if input.__class__.__name__ == "str":
return True
return False