文字列が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()
のドキュメントで説明されています)。
チェックする別の方法はありますか?
回答:
def is_ascii(s):
return all(ord(c) < 128 for c in s)
ord(c) < 128
無限よりも読みやすく、直感的であるc <= "\x7F"
あなたは正しい質問をしていないと思います-
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"
str
Python 2、bytes
Python 3)で使用しているためです。
str
ISOエンコーディングのA は、最初にUnicodeにエンコードする必要があります。答えはこれに入るはずです。
s.decode('ascii') if isinstance(s, bytes) else s.encode('ascii')
Python 3では、入力タイプに応じて両方を使用する必要があります。OPの入力はバイト文字列'é'
(Python 2構文、Python 3はその時点ではリリースされていません)であり、したがって.decode()
正しいです。
str
Python 2ではバイト文字列です。.decode('ascii')
すべてのバイトがASCII範囲内にあるかどうかを調べるために使用するのは正しいことです。
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
isascii
、文字列を渡す関数になりました:isascii('somestring')
== True
およびisascii('àéç')
==False
try: s.encode('ascii'); return True
except UnicodeEncodeError: return False
(上記と同様ですが、文字列はPython 3のUnicodeであるため、エンコーディングです)。サロゲートがある場合、この回答はPython 3でもエラーを発生させます(たとえばisascii('\uD800')
、を返すのではなくエラーを発生させますFalse
)
文字列の面倒/非効率なasciiチェックが不要になり、新しい組み込みのstr
/ bytes
/ bytearray
メソッド- .isascii()
文字列がasciiかどうかをチェックします。
print("is this ascii?".isascii())
# True
"\x03".isascii()
も真です。ドキュメントでは、これはすべての文字がコードポイント128(0〜127)未満であることを確認するだけであると述べています。制御文字も避けたい場合は、次のものが必要ですtext.isascii() and text.isprintable()
。isprintable
¿のような文字は(正しく)印刷可能であると見なされるため、単独で使用するだけでも十分ではありませんが、ASCII印刷可能セクション内にはないため、両方が必要な場合は両方をチェックする必要があります。さらに別の落とし穴:スペースは印刷可能と見なされますが、タブと改行はそうではありません。
最近このようなものに遭遇-将来の参考のために
import chardet
encoding = chardet.detect(string)
if encoding['encoding'] == 'ascii':
print 'string is in ascii'
あなたはそれを使うことができます:
string_ascii = string.decode(encoding['encoding']).encode('ascii')
{'confidence': 0.99, 'encoding': 'EUC-JP'}
(この場合は完全に間違っていました)
Vincent Marchettiは正しい考えをstr.decode
持っていますが、Python 3では非推奨になりました。Python3では、次のコマンドで同じテストを行うことができます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'
この文字は、実際には、書記素または文字のいずれかを表す単一または複数の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用語集は、特定の各用語がテキスト表現の異なる部分をどのように参照するかを指摘することにより、これらの問題のいくつかを理解するのに役立つガイドになる可能性があり、多くのプログラマーが理解するよりもはるかに複雑です。
これはどうですか?
import string
def isAscii(s):
for c in s:
if c not in string.ascii_letters:
return False
return True
エンコーディングがわからない文字列を使用/エンコード/デコードする方法(およびその文字列内の特殊文字をエスケープ/変換する方法)を決定しようとしたときに、この質問を見つけました。
私の最初のステップは、文字列のタイプをチェックすることでした。タイプからフォーマットに関する適切なデータを取得できることに気づきませんでした。 この回答は非常に役に立ち、私の問題の根本原因になりました。
あなたが失礼でしつこくなっているなら
UnicodeDecodeError: 'ascii'コーデックは、263桁目のバイト0xc3をデコードできません:序数が範囲(128)にありません
特にエンコードする場合は、すでにUnicodeになっている文字列をunicode()しようとしないようにしてください。なんらかの理由で、ASCIIコーデックエラーが発生します。(これがどれほどひどいのかをよりよく理解するには、Python KitchenレシピとPython docs tutorials も参照してください。)
結局、私がやりたかったのはこれだと判断しました。
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')
'àéç'
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:]]定義を受け入れる正規表現ライブラリを使用できます。
クラッシュからあなたのコードを防ぐために、あなたは多分使用したい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
try
ラッパーは完全に無意味です。"¶"
がUnicode文字列の場合はord("¶")
機能し、そうでない場合(Python 2)はfor c in s
それをバイトに分解するためord
、機能し続けます。
以下を使用して、文字列が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
is_ascii(u'i am ascii')
。文字とスペースは間違いなくASCIIですがFalse
、文字列をに強制したため、これはまだ返されますunicode
。