Подтвердить что ты не робот

Как определить длину байта строки, кодированной utf-8, в Python?

Я работаю с загрузками Amazon S3, и у меня возникают проблемы с длинными именами клавиш. S3 ограничивает длину ключа байтами, а не символами.

Из документов:

Имя ключа представляет собой последовательность символов Юникода, кодировка UTF-8 которой составляет не более 1024 байтов.

Я также пытаюсь встроить метаданные в имя файла, поэтому мне нужно уметь вычислять текущую длину байта строки с помощью Python, чтобы убедиться, что метаданные не слишком долго делают ключ (в этом случае я бы для использования отдельного файла метаданных).

Как определить длину байта строки, кодированной utf-8? Опять же, меня не интересует длина символа... скорее, фактическая длина байта, используемая для хранения строки.

4b9b3361

Ответ 1

def utf8len(s):
    return len(s.encode('utf-8'))

Прекрасно работает в Python 2 и 3.

Ответ 2

Используйте метод 'encode' для преобразования из символьной строки в байтовую строку, затем используйте len(), как обычно:

>>> s = u"¡Hola, mundo!"                                                      
>>> len(s)                                                                    
13 # characters                                                                             
>>> len(s.encode('utf-8'))   
14 # bytes

Ответ 3

Кодирование строки и использование 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)