Generación aleatoria de cadenas con letras mayúsculas y dígitos
¿Cómo genero una cadena de tamaño N, hecha de números y letras mayúsculas en inglés como por ejemplo:
- 6U1S75
- 4Z4UKK
- U911K4
Responde en una línea:
''.join(random.choice(string.ascii_uppercase + string.digits) for _ in range(N))
o incluso más corto comenzando con Python 3.6 usando random.choices()
:
''.join(random.choices(string.ascii_uppercase + string.digits, k=N))
Una versión criptográficamente más segura: vea esta publicación
''.join(random.SystemRandom().choice(string.ascii_uppercase + string.digits) for _ in range(N))
En detalles, con una función de limpieza para su posterior reutilización:
>>> import string
>>> import random
>>> def id_generator(size=6, chars=string.ascii_uppercase + string.digits):
... return ''.join(random.choice(chars) for _ in range(size))
...
>>> id_generator()
'G5G74W'
>>> id_generator(3, "6793YUIO")
'Y3U'
Como funciona ?
Importamos string
, un módulo que contiene secuencias de caracteres ASCII comunes, y random
, un módulo que se ocupa de la generación aleatoria.
string.ascii_uppercase + string.digits
simplemente concatena la lista de caracteres que representan dígitos y caracteres ASCII en mayúsculas:
>>> string.ascii_uppercase
'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
>>> string.digits
'0123456789'
>>> string.ascii_uppercase + string.digits
'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'
Luego usamos una lista por comprensión para crear una lista de 'n' elementos:
>>> range(4) # range create a list of 'n' numbers
[0, 1, 2, 3]
>>> ['elem' for _ in range(4)] # we use range to create 4 times 'elem'
['elem', 'elem', 'elem', 'elem']
En el ejemplo anterior, usamos [
para crear la lista, pero no lo hacemos en la id_generator
función, por lo que Python no crea la lista en la memoria, sino que genera los elementos sobre la marcha, uno por uno (más sobre esto aquí ).
En lugar de pedir que se cree 'n' veces la cadena elem
, le pediremos a Python que cree 'n' veces un carácter aleatorio, elegido de una secuencia de caracteres:
>>> random.choice("abcde")
'a'
>>> random.choice("abcde")
'd'
>>> random.choice("abcde")
'b'
Por tanto random.choice(chars) for _ in range(size)
realmente se trata de crear una secuencia de size
personajes. Personajes elegidos al azar entre chars
:
>>> [random.choice('abcde') for _ in range(3)]
['a', 'b', 'b']
>>> [random.choice('abcde') for _ in range(3)]
['e', 'b', 'e']
>>> [random.choice('abcde') for _ in range(3)]
['d', 'a', 'c']
Luego simplemente los unimos con una cadena vacía para que la secuencia se convierta en una cadena:
>>> ''.join(['a', 'b', 'b'])
'abb'
>>> [random.choice('abcde') for _ in range(3)]
['d', 'c', 'b']
>>> ''.join(random.choice('abcde') for _ in range(3))
'dac'
Esta pregunta de Stack Overflow es el resultado principal actual de Google para "Python de cadena aleatoria". La respuesta principal actual es:
''.join(random.choice(string.ascii_uppercase + string.digits) for _ in range(N))
Este es un método excelente, pero el PRNG aleatorio no es criptográficamente seguro. Supongo que muchas personas que investigan esta pregunta querrán generar cadenas aleatorias para cifrado o contraseñas. Puedes hacer esto de forma segura realizando un pequeño cambio en el código anterior:
''.join(random.SystemRandom().choice(string.ascii_uppercase + string.digits) for _ in range(N))
Usar random.SystemRandom()
en lugar de usar aleatoriamente /dev/urandom en máquinas *nix y CryptGenRandom()
en Windows. Estos son PRNG criptográficamente seguros. Usarlo random.choice
en lugar de random.SystemRandom().choice
en una aplicación que requiere un PRNG seguro podría ser potencialmente devastador y, dada la popularidad de esta pregunta, apuesto a que ese error ya se ha cometido muchas veces.
Si está utilizando python3.6 o superior, puede utilizar el nuevo módulo de secretos como se menciona en la respuesta de MSeifert :
''.join(secrets.choice(string.ascii_uppercase + string.digits) for _ in range(N))
Los documentos del módulo también analizan formas convenientes de generar tokens seguros y las mejores prácticas .
Simplemente use el uuid integrado de Python:
Si los UUID son adecuados para sus propósitos, utilice el paquete uuid integrado .
Solución de una línea:
import uuid; uuid.uuid4().hex.upper()[0:6]
Versión en profundidad:
Ejemplo:
import uuid
uuid.uuid4() #uuid4 => full random uuid
# Outputs something like: UUID('0172fc9a-1dac-4414-b88d-6b9a6feb91ea')
Si necesita exactamente su formato (por ejemplo, "6U1S75"), puede hacerlo así:
import uuid
def my_random_string(string_length=10):
"""Returns a random string of length string_length."""
random = str(uuid.uuid4()) # Convert UUID format to a Python string.
random = random.upper() # Make all characters uppercase.
random = random.replace("-","") # Remove the UUID '-'.
return random[0:string_length] # Return the random string.
print(my_random_string(6)) # For example, D9E50C
Una forma más simple, más rápida pero un poco menos aleatoria es usar random.sample
en lugar de elegir cada letra por separado. Si se permiten n repeticiones, amplíe su base aleatoria n veces, por ejemplo
import random
import string
char_set = string.ascii_uppercase + string.digits
print ''.join(random.sample(char_set*6, 6))
Nota: random.sample evita la reutilización de caracteres; multiplicar el tamaño del conjunto de caracteres hace posibles múltiples repeticiones, pero aún son menos probables que en una elección puramente aleatoria. Si elegimos una cadena de longitud 6 y elegimos 'X' como primer carácter, en el ejemplo de elección, las probabilidades de obtener 'X' para el segundo carácter son las mismas que las probabilidades de obtener 'X' como primer personaje. En la implementación de muestra aleatoria, las probabilidades de obtener 'X' como cualquier carácter posterior son solo 6/7 de las posibilidades de obtenerlo como el primer carácter.
import uuid
lowercase_str = uuid.uuid4().hex
lowercase_str
es un valor aleatorio como'cea8b32e00934aaea8c005a35d85a5c0'
uppercase_str = lowercase_str.upper()
uppercase_str
es'CEA8B32E00934AAEA8C005A35D85A5C0'