Как проверить, является ли строка unicode или ascii?
Что мне нужно сделать в Python, чтобы выяснить, какая кодировка?
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. Строка Юникода может состоять только из символов в диапазоне ASCII, а bytestring может содержать ASCII, кодированный Юникод или даже нетекстовые данные.
просто делать
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 все строки являются последовательностями символов Юникода. и достаточно выполнить проверку isinstance для str (что означает строку unicode по умолчанию).
isinstance(x, str)
в отношении python 2.икс, Большинство людей, похоже, используют оператор if, который имеет две проверки. для УЛ и для Юникода.
Если вы хотите проверить, есть ли у вас "строковый" объект с одним оператором, вы можете сделать следующее:
isinstance(x, basestring)
Unicode не является кодировкой-процитировать Кумара Макмиллана:
Если ASCII, UTF-8 и другие байтовые строки являются "текстовыми" ...
...тогда Юникод - это "text-ness";
это абстрактная форма текста
прочтите Макмиллана Unicode В Python, Полностью Демистифицированный talk от 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 не совсем справедливо говорить:
str
S-UTFx для любого x (например. В utf8)str
s являются Unicodestr
s-упорядоченные коллекции символов Юникода
в Python str
type - это (обычно) последовательность кодовых точек Unicode, некоторые из которых сопоставляются с символами.
даже на 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 использует заголовок Content-Type для этого.
Это может помочь кому-то еще, я начал тестирование для строкового типа переменной 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