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

StackOverflow https://stackoverflow.com/questions/196345

  •  10-07-2019
  •  | 
  •  

Вопрос

Я хочу проверить, находится ли строка в 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)

Другие советы

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

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

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

Новое в Python 3.7 ( bpo32677 )

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

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

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

import chardet

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

который вы могли бы использовать с

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

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

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

import string

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

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

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

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

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

  

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

особенно когда вы кодируете, убедитесь, что вы не пытаетесь unicode () строка, которая уже является unicode - по какой-то ужасной причине вы получаете ошибки кодека ascii. (См. Также рецепт Python Kitchen и учебники по Python для лучшего понимания того, насколько это может быть ужасно.)

В конце концов я решил, что хочу сделать следующее:

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

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

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

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

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

Как и ответ @ RogerDahl на ответ , но эффективнее закорачивать его путем отрицания класса символов и использования поиска вместо < code> 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

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

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

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

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

, s))

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

Я использую следующее, чтобы определить, является ли строка 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
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top