Как проверить, есть ли строка в Python в ASCII? - PullRequest
183 голосов
/ 13 октября 2008

Я хочу проверить, есть ли строка в ASCII или нет.

Мне известно о ord(), однако, когда я пытаюсь ord('é'), у меня появляется TypeError: ord() expected a character, but string of length 2 found. Я понял, что это вызвано тем, как я собрал Python (как объяснено в документации ord() )

Есть ли другой способ проверить?

Ответы [ 16 ]

241 голосов
/ 13 октября 2008

Я думаю, что вы не задаете правильный вопрос -

Строка в python не имеет свойства, соответствующего 'ascii', utf-8 или любой другой кодировке. Источник вашей строки (независимо от того, читаете ли вы ее из файла, вводите с клавиатуры и т. Д.), Возможно, закодировал строку unicode в ascii для создания вашей строки, но вам нужно найти ответ.

Возможно, вы можете задать вопрос: "Является ли эта строка результатом кодирования строки Unicode в 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"
150 голосов
/ 13 октября 2008
def is_ascii(s):
    return all(ord(c) < 128 for c in s)
139 голосов
/ 23 августа 2013

Python 3 way:

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
20 голосов
/ 09 августа 2011

Недавно столкнулся с чем-то подобным - для дальнейшего использования

import chardet

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

который вы можете использовать с:

string_ascii = string.decode(encoding['encoding']).encode('ascii')
18 голосов
/ 02 июля 2018

Новое в Python 3.7 ( bpo32677 )

Больше нет утомительных / неэффективных проверок ascii для строк, новый встроенный метод str / bytes / bytearray - .isascii() проверит, является ли строка ascii.

print("is this ascii?".isascii())
# True
17 голосов
/ 14 октября 2008

Ваш вопрос неверный; ошибка, которую вы видите, является не результатом того, как вы создали Python, а из-за путаницы между строками байтов и строками Unicode.

Строки байтов (например, "foo" или "bar" в синтаксисе Python) являются последовательностями октетов; цифры от 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'

Этот символ на самом деле может быть представлен как одной или несколькими «кодовыми точками» Юникода, которые сами представляют либо графемы, либо символы. Это либо «е с острым акцентом (т.е. кодовая точка 233)», либо «е» (кодовая точка 101), за которым следует «острый акцент на предыдущий символ» (кодовая точка 770). Так что этот точно такой же символ может быть представлен как структура данных Python u'e\u0301' или u'\u00e9'.

В большинстве случаев вам не нужно об этом заботиться, но это может стать проблемой, если вы выполняете итерацию по строке в юникоде, так как итерация работает по кодам, а не по разложимым символам. Другими словами, len(u'e\u0301') == 2 и len(u'\u00e9') == 1. Если это имеет значение для вас, вы можете конвертировать между составными и разложенными формами, используя unicodedata.normalize.

Глоссарий Unicode может быть полезным руководством для понимания некоторых из этих проблем, указывая, как каждый конкретный термин относится к разной части представления текста, что гораздо сложнее, чем у многих программистов реализовать.

10 голосов
/ 02 сентября 2015

Винсент Маркетти имеет правильную идею, но 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 голосов
/ 13 октября 2008

Как насчет этого?

import string

def isAscii(s):
    for c in s:
        if c not in string.ascii_letters:
            return False
    return True
9 голосов
/ 22 августа 2012

Я нашел этот вопрос, пытаясь определить, как использовать / кодировать / декодировать строку, в кодировке которой я не был уверен (и как экранировать / преобразовать специальные символы в этой строке).

Моим первым шагом должна была быть проверка типа строки - я не понимал, что могу получить хорошие данные о ее форматировании из типов (типов). Этот ответ был очень полезным и дошел до сути моих проблем.

Если вы становитесь грубыми и настойчивыми

UnicodeDecodeError: кодек «ascii» не может декодировать байт 0xc3 в позиции 263: порядковый номер не в диапазоне (128)

особенно, когда вы ENCODING, убедитесь, что вы не пытаетесь 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;'
4 голосов
/ 22 мая 2015

Чтобы улучшить решение Александра из Python 2.6 (и в Python 3.x), вы можете использовать вспомогательный модуль 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)
...