파이썬에서 문자열이 ASCII인지 확인하는 방법?


211

문자열이 ASCII인지 여부를 확인하고 싶습니다.

나는 알고 ord()있지만 ord('é'), 시도 할 때 나는있다 TypeError: ord() expected a character, but string of length 2 found. 필자는 파이썬을 구축 한 방식으로 인해 발생한다는 것을 이해했습니다 ( ord()문서에 설명되어 있음 ).

확인하는 다른 방법이 있습니까?


문자열 인코딩은 Python 2와 Python 3에서 상당히 다르므로 어떤 버전을 타겟팅하고 있는지 아는 것이 좋습니다.
— florisla

답변:


188
def is_ascii(s):
    return all(ord(c) < 128 for c in s)

95
무의미하게 비효율적입니다. Vincent Marchetti가 제안한 것처럼 s.decode ( 'ascii')를 시도하고 UnicodeDecodeError를 잡는 것이 훨씬 좋습니다.
— ddaa

20
비효율적이지 않습니다. all ()은 유효하지 않은 바이트를 만나면 단락되고 False를 반환합니다.
— John Millikin

10
비효율적이든 아니든간에, 더 파이썬적인 방법은 시도 / 제외입니다.
— Jeremy Cantrell

43
시도 / 제외에 비해 비효율적입니다. 여기서 루프는 인터프리터에 있습니다. try / except 형식을 사용하면 루프는 str.decode ( 'ascii')에 의해 호출 된 C 코덱 구현에 있습니다. 그리고 나는 try / except 형식이 더 파이썬이라는 것에 동의합니다.
— ddaa

25
@JohnMachin는 ord(c) < 128것보다 무한히 더 읽기 쉽고 직관적c <= "\x7F"
— 슬레이터 Victoroff

253

당신이 옳은 질문을하지 않는 것 같아요.

파이썬의 문자열에는 'ascii', utf-8 또는 기타 인코딩에 해당하는 속성이 없습니다. 문자열의 소스 (파일에서 읽거나 키보드에서 입력하는 등)는 문자열을 생성하기 위해 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"

28
python 3에서는 문자열이없는 디코딩 방법이기 때문에 encode를 사용하는 것이 좋습니다. 인코딩 / 디코딩의 차이점
— Jet Guo

@Sri : 인코딩되지 않은 문자열 ( strPython 2, bytesPython 3)에서 사용하기 때문 입니다.
— dotancohen

Python 2에서이 솔루션은 유니 코드 문자열 에서만 작동 합니다. str모든 ISO 인코딩에서 A 를 먼저 유니 코드로 인코딩해야합니다. 대답은 이것에 들어가야합니다.
— Alexis

@JetGuo : s.decode('ascii') if isinstance(s, bytes) else s.encode('ascii')파이썬 3에서 입력 유형에 따라 두 가지를 모두 사용해야합니다. OP의 입력은 바이트 문자열 'é'(파이썬 2 구문, 파이썬 3은 당시에 릴리스되지 않았습니다)이므로 .decode()정확합니다.
— jfs

2
@alexis : 잘못되었습니다. str파이썬 2에서는 바이트 문자열입니다. .decode('ascii')모든 바이트가 ASCII 범위에 있는지 확인하는 데 사용 하는 것이 좋습니다 .
— jfs

153

파이썬 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

7
이것은 python3에서 거의 모든 문자열 인 유니 코드 문자열에서 ASCII가 아닌 문자를 감지하는 좋은 방법입니다. ASCII 문자는 1 바이트 만 사용하여 인코딩 할 수 있으므로 모든 ASCII 문자 길이는 바이트로 인코딩 된 후 크기에 따라 다릅니다. 반면 ASCII 이외의 다른 문자는 2 바이트 또는 3 바이트로 인코딩되어 크기가 커집니다.
— Devy

@far로 가장 좋은 대답이지만…와 같은 일부 문자는 ascii처럼 보일 수 있습니다. 따라서 영어 텍스트를 감지하기 위해이 문자를 사용하려는 경우 확인하기 전에 이러한 문자를 대체해야합니다.
— Christophe Roussy

1
그러나 Python2에서는 UnicodeEncodeError가 발생합니다. Py2와 Py3에 대한 솔루션을 찾았습니다
— alvas

2
람다 사용에 익숙하지 않은 사람들을 위해 (이 답변을 처음 isasciiisascii('somestring')Trueisascii('àéç')False
— 접했

8
이것은 단지 낭비입니다. 문자열을 UTF-8로 인코딩하여 다른 전체 바이트 문자열을 만듭니다. 진정한 파이썬 3 방식은 try: s.encode('ascii'); return True except UnicodeEncodeError: return False(위와 비슷하지만 파이썬 3에서는 문자열이 유니 코드이므로 인코딩) 이 답변은 또한 대리가있을 때 Python 3에서 오류를 발생시킵니다 (예 : isascii('\uD800')반환하는 대신 오류 발생 False)
— Artyer

72

Python 3.7의 새로운 기능 ( bpo32677 )

문자열에 대한 더 이상 번거롭고 비효율적 인 ASCII 검사, 새로운 내장 str/ bytes/ bytearray방법- .isascii()문자열이 ASCII인지 확인합니다.

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

이것은 정상에 있어야합니다!
— Salek

"\x03".isascii()또한 사실입니다. 문서에 따르면 모든 문자가 코드 포인트 128 (0-127) 미만인지 확인합니다. 제어 문자도 피하려면 다음이 필요 text.isascii() and text.isprintable()합니다.. 그냥 사용 isprintable자체 것은 ¿ 같은 문자가 (제대로) 인쇄로 간주되므로, 충분한 또한,하지만 당신은 모두 당신이 모두를 원하는 경우 확인해야합니다 그래서, 아스키 인쇄 섹션 내에 아니다. 또 다른 문제 : 공백은 인쇄 가능한 것으로 간주되며 탭과 줄 바꿈은 그렇지 않습니다.
— Luc

19

최근에 이와 같은 문제가 발생했습니다. 나중에 참조 할 수 있습니다.

import chardet

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

당신이 함께 사용할 수있는 :

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

7
물론 이것은 chardet 라이브러리 가 필요합니다 .
— StackExchange saddens dancek

1
예, 대부분의 설치에서 기본적으로 chardet을 사용할 수 있습니다
— Alvin

7
chardet 은 다음과 같은 특정 확률로 인코딩을 추측합니다. {'confidence': 0.99, 'encoding': 'EUC-JP'}(이 경우에는 완전히 틀 렸습니다)
— Suzana

19

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.


OP의 입력은 바이트 문자열입니다 ( bytes파이썬 3에서는 .encode()메소드 가없는 유형 ). .decode()@Vincent Marchetti의 대답은 정확합니다 .
— jfs

@JFSebastian OP는 "파이썬에서 문자열이 ASCII인지 확인하는 방법"을 묻습니다. 바이트 대 유니 코드 문자열을 지정하지 않습니다. 왜 입력을 바이트 스트링이라고합니까?
— drs

1
질문 날짜를보십시오 : 'é'당시 바이트 문자열이었습니다.
— jfs

1
@JFSebastian, 알았어.이 답변이 오늘 질문 된 것처럼이 질문에 대답한다고 생각하면 여전히 유효하고 도움이된다고 생각합니다. 적은 적은 사람들이 2008 년에 파이썬을 실행하는 것처럼 답을 찾고 여기에 올 것이다
— DRS

2
python3에 대한 솔루션을 검색 할 때이 질문을 발견하고 신속하게 질문을 읽으면 이것이 python 2 specfic이라고 의심하지는 않습니다. 그러나이 답변은 정말 도움이되었습니다.
— josch

17

질문이 잘못되었습니다. 당신이 보는 오류는 파이썬을 어떻게 빌드했는지에 대한 결과가 아니라 바이트 문자열과 유니 코드 문자열 사이의 혼란의 결과입니다.

바이트 문자열 (예 : 파이썬 구문에서 "foo"또는 "bar")은 8 진수 시퀀스입니다. 0-255 사이의 숫자. 유니 코드 문자열 (예 : u "foo"또는 u'bar ')은 유니 코드 코드 포인트의 시퀀스입니다. 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'.

대부분 걱정할 필요는 없지만, 유니 코드 문자열을 반복하는 경우 분해 할 수있는 문자가 아닌 코드 포인트별로 반복이 작동하므로 문제가 될 수 있습니다. 즉, len(u'e\u0301') == 2과 len(u'\u00e9') == 1. 이것이 당신에게 중요하다면,를 사용하여 작성된 양식과 분해 된 양식을 변환 할 수 있습니다 unicodedata.normalize.

유니 코드 용어집 은 각 특정 용어가 텍스트 표현의 다른 부분을 어떻게 나타내는지를 지적함으로써 이러한 문제 중 일부를 이해하는 데 유용한 안내서가 될 수 있습니다. 이는 많은 프로그래머가 인식하는 것보다 훨씬 복잡합니다.


3
'é'가 반드시 단일 코드 포인트를 나타내는 것은 아닙니다 . 이 수 개의 코드 포인트 (+ 0,065 + U는 U + 0301)를.
— jfs

2
각 추상 문자는 항상 단일 코드 포인트로 표시됩니다. 그러나 인코딩 방식에 따라 코드 포인트가 여러 바이트로 인코딩 될 수 있습니다. 즉, 'é'는 UTF-8과 UTF-16에서 2 바이트이고 UTF-32에서 4 바이트이지만 각 경우 여전히 단일 코드 포인트 (U + 00E9)입니다.
— Ben Blank

5
@ 벤 빈 : U + 0065과 U + 0301가 있는 코드 포인트 그들이 할 수있는 'E'대표 도 U + 00E9으로 나타낼 수있다. 구글 "급성 악센트 결합".
— jfs

JF는 U + 0065와 U + 0301을 결합하여 'é'를 형성하는 것이 옳지 만 이것은 가역적 인 펑 티노가 아닙니다. U + 00E9를 얻게됩니다. 에 따르면 위키 피 디아 , 이러한 복합 코드 포인트는 이전 버전과의 호환성을 위해 유용하다
— 마틴 코네 크니

1
@teehoo-작성된 문자를 나타내는 코드 포인트를 동일한 구성된 문자를 나타내는 코드 포인트 시퀀스로 다시 정규화 할 수 있다는 점에서 가역적 인 기능입니다. 파이썬에서는 다음과 같이 할 수 있습니다 : unicodedata.normalize ( 'NFD', u '\ xe9').
— 글리프

10

이건 어때?

import string

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

5
문자열에 문자가 아닌 ASCII 문자가 포함되어 있으면 실패합니다. 줄 바꿈, 공백, 점, 쉼표, 밑줄 및 괄호가 포함 된 코드 예제입니다.
— florisla

9

인코딩이 확실하지 않은 문자열을 사용 / 인코딩 / 디코딩하는 방법 (및 해당 문자열의 특수 문자를 이스케이프 / 변환하는 방법)을 결정하는 동안이 질문을 발견했습니다.

첫 번째 단계는 문자열 유형을 확인하는 것이 었습니다. 유형에서 형식에 대한 좋은 데이터를 얻을 수 있다는 것을 알지 못했습니다. 이 답변은 매우 도움이되었고 내 문제의 근원에 도달했습니다.

무례하고 끈질긴 경우

UnicodeDecodeError : 'ascii'코덱이 263 위치에서 바이트 0xc3을 디코딩 할 수 없습니다 : 서 수가 범위 내에 있지 않습니다 (128)

특히 인코딩 할 때 어떤 끔찍한 이유로 이미 유니 코드 인 문자열을 유니 코드 ()하려고 시도하지 마십시오. 아스키 코덱 오류가 발생합니다. ( Python Kitchen 레시피 및 Python 문서 도 참조하십시오. 자습서를 이것이 얼마나 끔찍한 지 이해하십시오.)

결국 나는 내가하고 싶은 것이 이것이라고 결정했다.

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

디버깅에 도움이되는 것은 내 파일의 기본 코딩을 utf-8로 설정하는 것입니다 (파이썬 파일의 시작 부분에 넣으십시오).

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

따라서 유니 코드 이스케이프 (u '\ xe0 \ xe9 \ xe7')를 사용하지 않고도 특수 문자 ( 'àéç')를 테스트 할 수 있습니다.

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

4

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)


2

Posix 표준 [[: ASCII :]] 정의를 허용하는 정규식 라이브러리를 사용할 수 있습니다.


2

str파이썬에서 찌르기 ( -type)는 일련의 바이트입니다. 이 일련의 바이트가 ASCII 문자열을 나타내는 지, ISO-8859-1과 같은 8 비트 문자 세트의 문자열 또는 UTF-8 또는 UTF-16으로 인코딩 된 문자열을 나타내는 지 여부를 알 수있는 방법 은 없습니다. .

그러나 사용 된 인코딩을 알고 있으면 decodestr을 유니 코드 문자열로 만든 다음 정규 표현식 (또는 루프)을 사용하여 관심 범위를 벗어난 문자가 포함되어 있는지 확인할 수 있습니다.


1

@RogerDahl의 답변과 비슷하지만 문자 클래스를 무시 하고 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
import re

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

ASCII 빈 문자열을 포함하려면 변경 +에 *.


-1

코드 충돌을 방지하기 위해 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

이 try포장지는 완전히 무의미합니다. 경우 "¶"유니 코드 문자열은 다음 ord("¶")작동합니다, 그것은 (파이썬 2)이 아니라면, for c in s그래서 바이트로 분해됩니다 ord계속 작동합니다.
— Ry-

-5

문자열을 ASCII 또는 유니 코드인지 확인하려면 다음을 사용하십시오.

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

4
-1 AARRGGHH 이것은 범위 (128, 256)의 ord (c)를 가진 모든 문자를 ASCII로 취급합니다 !!!
— John Machin

작동하지 않습니다. 다음을 호출하십시오 is_ascii(u'i am ascii').. 문자와 공백이 ASCII 인 경우에도 False문자열을 강제 로 했기 때문에 여전히 반환 unicode됩니다.
— jpmc26
당사 사이트를 사용함과 동시에 당사의 쿠키 정책과 개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.