Ответ 1
def utf8len(s):
return len(s.encode('utf-8'))
Прекрасно работает в Python 2 и 3.
Я работаю с загрузками Amazon S3, и у меня возникают проблемы с длинными именами клавиш. S3 ограничивает длину ключа байтами, а не символами.
Из документов:
Имя ключа представляет собой последовательность символов Юникода, кодировка UTF-8 которой составляет не более 1024 байтов.
Я также пытаюсь встроить метаданные в имя файла, поэтому мне нужно уметь вычислять текущую длину байта строки с помощью Python, чтобы убедиться, что метаданные не слишком долго делают ключ (в этом случае я бы для использования отдельного файла метаданных).
Как определить длину байта строки, кодированной utf-8? Опять же, меня не интересует длина символа... скорее, фактическая длина байта, используемая для хранения строки.
def utf8len(s):
return len(s.encode('utf-8'))
Прекрасно работает в Python 2 и 3.
Используйте метод 'encode' для преобразования из символьной строки в байтовую строку, затем используйте len(), как обычно:
>>> s = u"¡Hola, mundo!"
>>> len(s)
13 # characters
>>> len(s.encode('utf-8'))
14 # bytes
Кодирование строки и использование len
в результате отлично работают, как показали другие ответы. Ему нужно создать отбрасываемую копию строки - если вы работаете с очень большими строками, это может быть не оптимальным (я не считаю 1024 байтов большим, хотя). Структура UTF-8 позволяет легко получить длину каждого символа без его кодирования, хотя кодирование одного символа может быть проще. Здесь представлены оба метода, они должны дать тот же результат.
def utf8_char_len_1(c):
codepoint = ord(c)
if codepoint <= 0x7f:
return 1
if codepoint <= 0x7ff:
return 2
if codepoint <= 0xffff:
return 3
if codepoint <= 0x10ffff:
return 4
raise ValueError('Invalid Unicode character: ' + hex(codepoint))
def utf8_char_len_2(c):
return len(c.encode('utf-8'))
utf8_char_len = utf8_char_len_1
def utf8len(s):
return sum(utf8_char_len(c) for c in s)