Как проверить, является ли строка unicode или ascii?



Что мне нужно сделать в Python, чтобы выяснить, какая кодировка?

1010   10  

10 ответов:

в Python 3 все строки являются последовательностями символов Юникода. Там есть bytes тип, который содержит необработанные байты.

в Python 2, строка может быть вида str или типа unicode. Вы можете сказать, что с помощью кода что-то вроде этого:

def whatisthis(s):
    if isinstance(s, str):
        print "ordinary string"
    elif isinstance(s, unicode):
        print "unicode string"
    else:
        print "not a string"

это не различает "Unicode или ASCII"; он различает только типы Python. Строка Unicode может состоять из чисто символов в диапазоне ASCII, а bytestring может содержать ASCII, кодированный Unicode или даже нетекстовые данные.

просто делать

type(s)

одно скажу unicode, другой скажет str.

вы можете обрабатывать их отдельно с помощью isinstance, например,

if isinstance(s, str):
    print 's is a string object'
elif isinstance(s, unicode):
    print 's is a unicode object'

или вы хотите сказать, что у вас есть str, и вы пытаетесь выяснить, если он закодирован с помощью ASCII или UTF-8 или что-то еще?

в таком случае, попробуйте это:

s.decode('ascii')

если он вызывает исключение, строка не является 100% ASCII.

в python 3.X все строки представляют собой последовательности символов Unicode. и выполнение проверки isinstance для str (что означает строку unicode по умолчанию) должно быть достаточным.

isinstance(x, str)

что касается python 2.икс, Большинство людей, похоже, используют оператор if, который имеет две проверки. для УЛ и для Юникода.

Если вы хотите проверить, есть ли у вас "строковый" объект с одним оператором, вы можете сделать следующее:

isinstance(x, basestring)

Unicode - это не кодировка-цитирую Кумара Макмиллана:

Если ASCII, UTF-8 и другие байтовые строки являются "текстовыми" ...

...тогда Unicode - это "text-ness";

это абстрактная форма текста

почитайте Макмиллана Unicode В Python, Полностью Демистифицированный поговорите с PyCon 2008, это объясняет вещи намного лучше, чем большинство связанных ответов на переполнение стека.

если ваш код должен быть совместим с и Python 2 и Python 3, Вы не можете напрямую использовать такие вещи, как isinstance(s,bytes) или isinstance(s,unicode) не оборачивая их ни в try / except, ни в тест версии python, потому что bytes не определено в Python 2 и unicode не определено в Python 3.

есть некоторые уродливые обходные пути. Крайне некрасиво сравнивать имя типа, вместо сравнения самого типа. Вот пример:

# convert bytes (python 3) or unicode (python 2) to str
if str(type(s)) == "<class 'bytes'>":
    # only possible in Python 3
    s = s.decode('ascii')  # or  s = str(s)[2:-1]
elif str(type(s)) == "<type 'unicode'>":
    # only possible in Python 2
    s = str(s)

возможно, немного менее уродливым обходным путем является проверка номера версии Python, например:

if sys.version_info >= (3,0,0):
    # for Python 3
    if isinstance(s, bytes):
        s = s.decode('ascii')  # or  s = str(s)[2:-1]
else:
    # for Python 2
    if isinstance(s, unicode):
        s = str(s)

это unpythonic, и большую часть времени там, наверное, лучший способ.

использование:

import six
if isinstance(obj, six. text_type)

внутри шести библиотек он представляет собой:

if PY3:
    string_types = str,
else:
    string_types = basestring,

обратите внимание, что на Python 3, это не очень честно сказать:

  • strs являются UTFx для любого x (например. В utf8)

  • strс юникодом

  • str s-упорядоченные коллекции символов Юникода

в Python str тип - это (обычно) последовательность кодовых точек Юникода, некоторые из которых соответствуют символам.


даже на Python 3, это не так просто ответить на этот вопрос, как вы можете себе представить.

очевидный способ проверить ASCII-совместимые строки-это попытка кодирования:

"Hello there!".encode("ascii")
#>>> b'Hello there!'

"Hello there... ☃!".encode("ascii")
#>>> Traceback (most recent call last):
#>>>   File "", line 4, in <module>
#>>> UnicodeEncodeError: 'ascii' codec can't encode character '\u2603' in position 15: ordinal not in range(128)

ошибка различает случаи.

в Python 3, есть даже некоторые строки, которые содержат неверные кодовые точки Unicode:

"Hello there!".encode("utf8")
#>>> b'Hello there!'

"\udcc3".encode("utf8")
#>>> Traceback (most recent call last):
#>>>   File "", line 19, in <module>
#>>> UnicodeEncodeError: 'utf-8' codec can't encode character '\udcc3' in position 0: surrogates not allowed

используется тот же метод для их различения.

вы могли бы использовать Универсальный Детектор Кодирования, но имейте в виду, что это просто даст вам лучшее предположение, а не фактическое кодирование, потому что невозможно узнать кодировку строки "abc", например. Вам нужно будет получить информацию о кодировке в другом месте, например, протокол HTTP использует заголовок типа контента для этого.

Это может помочь кому-то еще, я начал тестирование для строкового типа переменной s, но для моего приложения было более разумно просто вернуть s как utf-8. Процесс, вызывающий return_utf, затем знает, с чем он имеет дело, и может обрабатывать строку соответствующим образом. Код не является первозданным, но я намерен, чтобы он был агностиком версии Python без теста версии или импорта шести. Пожалуйста, прокомментируйте с улучшениями в примере кода ниже, чтобы помочь другим людям.

def return_utf(s):
    if isinstance(s, str):
        return s.encode('utf-8')
    if isinstance(s, (int, float, complex)):
        return str(s).encode('utf-8')
    try:
        return s.encode('utf-8')
    except TypeError:
        try:
            return str(s).encode('utf-8')
        except AttributeError:
            return s
    except AttributeError:
        return s
    return s # assume it was already utf-8

для совместимости py2 / py3 просто используйте

import six if isinstance(obj, six.text_type)

Comments

    Ничего не найдено.