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

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

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

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

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

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

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

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

Используйте метод string '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)