Как проверить, находится ли строка в Python в ASCII?

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

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

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

Ответ 1

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

Ответ 2

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

Строка в 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"

Ответ 3

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

Ответ 4

В последнее время появилось нечто подобное - для дальнейшего использования

import chardet

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

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

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

Ответ 5

Ваш вопрос неверен; ошибка, которую вы видите, не является результатом того, как вы построили 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'

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

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

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

Ответ 6

Новое в Python 3.7 (bpo32677)

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

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

Ответ 7

Как это сделать?

import string

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

Ответ 8

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

Ответ 9

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

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

Если вы получаете грубое и постоянное

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

особенно когда вы ENCODING, убедитесь, что вы не пытаетесь выполнить unicode() строку, которая уже является unicode - по какой-то страшной причине вы получаете ошибки ascii в коде 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')
'&#224;&#233;&#231;'

Ответ 10

Чтобы улучшить решение Alexander из 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)

Ответ 11

Вы можете использовать библиотеку регулярных выражений, которая принимает стандартное определение Posix [[: ASCII:]].

Ответ 12

Укус (str -type) в Python - это серия байтов. Существует нет способа рассказать только о том, что эта строка байтов представляет собой строку ascii, строку в 8-битной кодировке, такую ​​как ISO-8859-1, или строку, закодированную с помощью UTF- 8 или UTF-16 или что-то еще.

Однако, если вы знаете используемую кодировку, вы можете decode str в строку юникода, а затем использовать регулярное выражение (или цикл), чтобы проверить, содержит ли он символы вне диапазона, о котором вы беспокоитесь.

Ответ 13

Чтобы предотвратить сбой кода, вы можете использовать try-except для catch 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

Ответ 14

import re

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

Чтобы включить пустую строку как ASCII, измените значение + на *.

Ответ 15

Как @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

Я предполагаю, что регулярное выражение хорошо оптимизировано для этого.

Ответ 16

Я использую следующее, чтобы определить, является ли строка 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