Generación aleatoria de cadenas con letras mayúsculas y dígitos

Resuelto Hellnar asked hace 14 años • 36 respuestas

¿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
Hellnar avatar Feb 13 '10 19:02 Hellnar
Aceptado

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.digitssimplemente 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_generatorfunció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 sizepersonajes. 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'
Ignacio Vazquez-Abrams avatar Feb 13 '2010 12:02 Ignacio Vazquez-Abrams

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.choiceen lugar de random.SystemRandom().choiceen 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 .

Randy Marsh avatar May 19 '2014 01:05 Randy Marsh

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
Bijan avatar Jun 26 '2013 15:06 Bijan

Una forma más simple, más rápida pero un poco menos aleatoria es usar random.sampleen 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.

Anurag Uniyal avatar Feb 13 '2010 12:02 Anurag Uniyal
import uuid
lowercase_str = uuid.uuid4().hex  

lowercase_stres un valor aleatorio como'cea8b32e00934aaea8c005a35d85a5c0'

uppercase_str = lowercase_str.upper()

uppercase_stres'CEA8B32E00934AAEA8C005A35D85A5C0'

Savad KP avatar Dec 01 '2015 10:12 Savad KP