Generar cadenas aleatorias UTF-8 en Python

Me gustaría probar el manejo de Unicode de mi código. ¿Hay algo que pueda poner en random.choice () para seleccionar todo el rango Unicode, preferiblemente no un módulo externo? Ni Google ni StackOverflow parecen tener una respuesta.

Edición: Parece que esto es más complejo de lo esperado, por lo que volveré a formular la pregunta: ¿es el siguiente código suficiente para generar todos los caracteres no de control válidos en Unicode ?

unicode_glyphs = ''.join( unichr(char) for char in xrange(1114112) # 0x10ffff + 1 if unicodedata.category(unichr(char))[0] in ('LMNPSZ') ) 

Hay una prueba de esfuerzo UTF-8 de Markus Kuhn que podrías usar.

Consulte también Really Good, Bad UTF-8 datos de prueba de ejemplo .

Las personas pueden encontrar su camino aquí basándose principalmente en el título de la pregunta, así que aquí hay una forma de generar una cadena aleatoria que contiene una variedad de caracteres Unicode. Para incluir más (o menos) posibles caracteres, simplemente extienda esa parte del ejemplo con los rangos de puntos de código que desee.

 import random def get_random_unicode(length): try: get_char = unichr except NameError: get_char = chr # Update this to include code point ranges to be sampled include_ranges = [ ( 0x0021, 0x0021 ), ( 0x0023, 0x0026 ), ( 0x0028, 0x007E ), ( 0x00A1, 0x00AC ), ( 0x00AE, 0x00FF ), ( 0x0100, 0x017F ), ( 0x0180, 0x024F ), ( 0x2C60, 0x2C7F ), ( 0x16A0, 0x16F0 ), ( 0x0370, 0x0377 ), ( 0x037A, 0x037E ), ( 0x0384, 0x038A ), ( 0x038C, 0x038C ), ] alphabet = [ get_char(code_point) for current_range in include_ranges for code_point in range(current_range[0], current_range[1] + 1) ] return ''.join(random.choice(alphabet) for i in range(length)) if __name__ == '__main__': print('A random string: ' + get_random_unicode(10)) 

Aquí hay una función de ejemplo que probablemente crea una secuencia aleatoria de UTF-8 bien formada, como se define en la Tabla 3–7 de Unicode 5.0.0:

 #!/usr/bin/env python3.1 # From Table 3–7 of the Unicode Standard 5.0.0 import random def byte_range(first, last): return list(range(first, last+1)) first_values = byte_range(0x00, 0x7F) + byte_range(0xC2, 0xF4) trailing_values = byte_range(0x80, 0xBF) def random_utf8_seq(): first = random.choice(first_values) if first <= 0x7F: return bytes([first]) elif first <= 0xDF: return bytes([first, random.choice(trailing_values)]) elif first == 0xE0: return bytes([first, random.choice(byte_range(0xA0, 0xBF)), random.choice(trailing_values)]) elif first == 0xED: return bytes([first, random.choice(byte_range(0x80, 0x9F)), random.choice(trailing_values)]) elif first <= 0xEF: return bytes([first, random.choice(trailing_values), random.choice(trailing_values)]) elif first == 0xF0: return bytes([first, random.choice(byte_range(0x90, 0xBF)), random.choice(trailing_values), random.choice(trailing_values)]) elif first <= 0xF3: return bytes([first, random.choice(trailing_values), random.choice(trailing_values), random.choice(trailing_values)]) elif first == 0xF4: return bytes([first, random.choice(byte_range(0x80, 0x8F)), random.choice(trailing_values), random.choice(trailing_values)]) print("".join(str(random_utf8_seq(), "utf8") for i in range(10))) 

Debido a la inmensidad del estándar Unicode, no puedo probar esto a fondo. También tenga en cuenta que los caracteres no están distribuidos equitativamente (pero cada byte en la secuencia es).

Depende de la forma en que desea realizar las pruebas y la precisión con la que desea hacer la generación. En su totalidad, Unicode es un conjunto de códigos de 21 bits (U + 0000 .. U + 10FFFF). Sin embargo, algunos fragmentos bastante grandes de ese rango se reservan para caracteres personalizados. ¿Desea preocuparse por generar caracteres combinados al comienzo de una cadena (porque solo deberían aparecer después de otro carácter)?

El enfoque básico que adoptaría es generar aleatoriamente un punto de código Unicode (por ejemplo, U + 2397 o U + 31232), validarlo en contexto (es un carácter legítimo; puede aparecer aquí en la cadena) y codificar puntos de código válidos en UTF-8.

Si solo desea comprobar si su código maneja el formato UTF-8 con formato incorrecto, puede usar esquemas de generación mucho más simples.

Tenga en cuenta que necesita saber qué esperar dada la entrada; de lo contrario, no está realizando pruebas; estás experimentando

Sigue un código que imprime cualquier carácter imprimible de UTF-8:

 print(''.join(tuple(chr(l) for l in range(1, 0x10ffff) if chr(l).isprintable()))) 

Todos los caracteres están presentes, incluso aquellos que no son manejados por la fuente utilizada. and not chr(l).isspace() se puede agregar and not chr(l).isspace() para filtrar todos los caracteres de espacio. (incluida la pestaña)

Dado que Unicode es solo un rango de códigos de pozo, ¿qué hay de usar unichr () para obtener la cadena de Unicode correspondiente a un número aleatorio entre 0 y 0xFFFF?
(Por supuesto, eso daría solo un punto de código, así que itere según sea necesario)

Puede descargar un sitio web escrito en griego o alemán que utiliza Unicode y enviarlo a su código.

Respondiendo a la pregunta revisada:

Sí, en una definición estricta de “caracteres de control”, tenga en cuenta que no incluirá CR, LF y TAB; ¿Es eso lo que quieres?

Considere responder a mi invitación anterior para decirnos lo que realmente está tratando de hacer.