open - python encode utf8
¿Cómo puedo determinar la longitud del byte de una cadena codificada en utf-8 en Python? (3)
Estoy trabajando con las subidas de Amazon S3 y tengo problemas con los nombres de las claves por ser demasiado largos. S3 limita la longitud de la clave por bytes, no por caracteres.
De la documentación:
El nombre de una clave es una secuencia de caracteres Unicode cuya codificación UTF-8 tiene una longitud máxima de 1024 bytes.
También intento incrustar metadatos en el nombre del archivo, por lo que necesito poder calcular la longitud del byte actual de la cadena usando Python para asegurarme de que los metadatos no hagan la clave demasiado larga (en cuyo caso tendría que usar un archivo de metadatos separado).
¿Cómo puedo determinar la longitud del byte de la cadena codificada en utf-8? De nuevo, no me interesa la longitud del carácter ... sino la longitud del byte real que se usa para almacenar la cadena.
Codificar la cadena y usar len
en el resultado funciona muy bien, como lo han demostrado otras respuestas. Es necesario crear una copia desechable de la cadena: si está trabajando con cadenas muy grandes, esto podría no ser óptimo (aunque no considero que 1024 bytes sean grandes ). La estructura de UTF-8 le permite obtener la longitud de cada carácter muy fácilmente sin siquiera codificarlo, aunque podría ser más fácil codificar un solo carácter. Presento ambos métodos aquí, deberían dar el mismo resultado.
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)
Use el método de cadena ''codificar'' para convertir de una cadena de caracteres a una cadena de bytes, luego use len () como normal:
>>> s = u"¡Hola, mundo!"
>>> len(s)
13 # characters
>>> len(s.encode(''utf-8''))
14 # bytes
def utf8len(s):
return len(s.encode(''utf-8''))
Funciona bien en Python 2 y 3.