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

Quiero generar una cadena de tamaño N.

Debe estar compuesto de números y letras mayúsculas en inglés, tales como:

  • 6U1S75
  • 4Z4UKK
  • U911K4

¿Cómo puedo lograr esto de una manera pythonica ?

Responda 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 https://stackoverflow.com/a/23728630/2213647 :

 ''.join(random.SystemRandom().choice(string.ascii_uppercase + string.digits) for _ in range(N)) 

En detalle, 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 caracteres y dígitos ASCII en mayúsculas:

 >>> string.ascii_uppercase 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' >>> string.digits '0123456789' >>> string.ascii_uppercase + string.digits 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789' 

Luego usamos una lista de 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 función id_generator , 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 crear ‘n’ veces el elemento de la cadena, le pediremos a Python que cree ‘n’ un carácter aleatorio, seleccionado de una secuencia de caracteres:

 >>> random.choice("abcde") 'a' >>> random.choice("abcde") 'd' >>> random.choice("abcde") 'b' 

Por lo tanto, random.choice(chars) for _ in range(size) realmente está creando una secuencia de caracteres de size . Caracteres que son escogidos al azar de los 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 sobre el desbordamiento de stack 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 al azar no es criptográficamente seguro. Supongo que muchas personas que investigan esta pregunta querrán generar cadenas aleatorias para el cifrado o las contraseñas. Puede hacer esto de manera segura haciendo un pequeño cambio en el código anterior:

 ''.join(random.SystemRandom().choice(string.ascii_uppercase + string.digits) for _ in range(N)) 

El uso de random.SystemRandom() lugar de solo usa aleatoriamente / dev / urandom en máquinas * nix y CryptGenRandom() en Windows. Estos son PRNGs criptográficamente seguros. Usar la random.SystemRandom().choice 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 el error ya se ha cometido muchas veces.

Si está usando python3.6 o superior, puede usar el nuevo módulo de secretos .

 ''.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 mejores prácticas .

Simplemente usa el uuid incorporado de Python:

Si los UUID están de acuerdo con sus propósitos, use el paquete uuid incorporado.

Una solución de línea:

import uuid; uuid.uuid4().hex.upper()[0:6]

En versión de 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 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, multiplicando el tamaño del conjunto de caracteres hace que sea posible realizar varias repeticiones, pero aún así es menos probable que estén en una elección aleatoria pura. Si optamos por una cadena de longitud 6, y seleccionamos ‘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 random.sample, las probabilidades de obtener ‘X’ como cualquier personaje posterior son solo 6/7 de la posibilidad de obtenerlo como el primer personaje

 import uuid lowercase_str = uuid.uuid4().hex 

lowercase_str es un valor aleatorio como 'cea8b32e00934aaea8c005a35d85a5c0'

 uppercase_str = lowercase_str.upper() 

uppercase_str es 'CEA8B32E00934AAEA8C005A35D85A5C0'

Tomando la respuesta de Ignacio, esto funciona con Python 2.6:

 import random import string N=6 print ''.join(random.choice(string.ascii_uppercase + string.digits) for _ in range(N)) 

Ejemplo de salida:

JQUBT2

Una forma más rápida, fácil y flexible de hacer esto es utilizar el módulo strgen ( pip install StringGenerator ).

Genere una cadena aleatoria de 6 caracteres con letras mayúsculas y dígitos:

 >>> from strgen import StringGenerator as SG >>> SG("[\u\d]{6}").render() u'YZI2CI' 

Consigue una lista única:

 >>> SG("[\l\d]{10}").render_list(5,unique=True) [u'xqqtmi1pOk', u'zmkWdUr63O', u'PGaGcPHrX2', u'6RZiUbkk2i', u'j9eIeeWgEF'] 

Garantiza un carácter “especial” en la cadena:

 >>> SG("[\l\d]{10}&[\p]").render() u'jaYI0bcPG*0' 

Un color HTML al azar:

 >>> SG("#[\h]{6}").render() u'#CEdFCa' 

etc.

Tenemos que ser conscientes de que esto:

 ''.join(random.choice(string.ascii_uppercase + string.digits) for _ in range(N)) 

Es posible que no tenga un dígito (o un carácter en mayúscula).

strgen es más rápido en tiempo de desarrollador que cualquiera de las soluciones anteriores. La solución de Ignacio es la ejecución más rápida en tiempo de ejecución y es la respuesta correcta utilizando la biblioteca estándar de Python. Pero casi nunca lo usarás en esa forma. Querrá usar SystemRandom (o fallback si no está disponible), asegúrese de que los juegos de caracteres necesarios estén representados, use unicode (o no), asegúrese de que las invocaciones sucesivas produzcan una cadena única, use un subconjunto de una de las clases de caracteres del módulo de cadena, Todo esto requiere mucho más código que en las respuestas proporcionadas. Los diversos bashs de generalizar una solución tienen limitaciones que Strgen resuelve con mayor brevedad y poder expresivo utilizando un lenguaje de plantilla simple.

Está en PyPI:

 pip install StringGenerator 

Divulgación: Soy el autor del módulo strgen.

Si necesita una cadena aleatoria en lugar de una pseudoaleatoria , debe usar os.urandom como la fuente

 from os import urandom from itertools import islice, imap, repeat import string def rand_string(length=5): chars = set(string.ascii_uppercase + string.digits) char_gen = (c for c in imap(urandom, repeat(1)) if c in chars) return ''.join(islice(char_gen, None, length)) 

Pensé que nadie había contestado esto todavía jajaja! Pero oye, aquí está mi propia oportunidad:

 import random def random_alphanumeric(limit): #ascii alphabet of all alphanumerals r = (range(48, 58) + range(65, 91) + range(97, 123)) random.shuffle(r) return reduce(lambda i, s: i + chr(s), r[:random.randint(0, len(r))], "") 

Basado en otra respuesta de desbordamiento de stack, la forma más liviana de crear una cadena aleatoria y un número hexadecimal aleatorio , una versión mejor que la respuesta aceptada sería:

 ('%06x' % random.randrange(16**6)).upper() 

mucho mas rápido.

Este método es un poco más rápido y un poco más molesto que el método random.choice () publicado por Ignacio.

Aprovecha la naturaleza de los algoritmos pseudoaleatorios y los bancos a nivel de bits y el desplazamiento son más rápidos que la generación de un nuevo número aleatorio para cada carácter.

 # must be length 32 -- 5 bits -- the question didn't specify using the full set # of uppercase letters ;) _ALPHABET = 'ABCDEFGHJKLMNPQRSTUVWXYZ23456789' def generate_with_randbits(size=32): def chop(x): while x: yield x & 31 x = x >> 5 return ''.join(_ALPHABET[x] for x in chop(random.getrandbits(size * 5))).ljust(size, 'A') 

… cree un generador que saque 5 números de bit a la vez 0..31 hasta que no quede ninguno

… unir () los resultados del generador en un número aleatorio con los bits correctos

Con Timeit, para cadenas de 32 caracteres, el tiempo fue:

 [('generate_with_random_choice', 28.92901611328125), ('generate_with_randbits', 20.0293550491333)] 

… pero para 64 cadenas de caracteres, randbits pierde;)

Probablemente nunca usaría este enfoque en el código de producción a menos que realmente no me gustaran mis compañeros de trabajo.

edición: se actualizó para adaptarse a la pregunta (solo en mayúsculas y dígitos), y use operadores a nivel de bit y & y >> en lugar de% y //

A partir de Python 3.6, debe usar el módulo de secrets si necesita que sea criptográficamente seguro en lugar del módulo random (de lo contrario, esta respuesta es idéntica a la de @Ignacio Vazquez-Abrams):

 from secrets import choice import string ''.join([choice(string.ascii_uppercase + string.digits) for _ in range(N)]) 

Una nota adicional: ¡una lista-comprensión es más rápida en el caso de str.join que usando una expresión de generador!

Lo haría de esta manera:

 import random from string import digits, ascii_uppercase legals = digits + ascii_uppercase def rand_string(length, char_set=legals): output = '' for _ in range(length): output += random.choice(char_set) return output 

O solo:

 def rand_string(length, char_set=legals): return ''.join( random.choice(char_set) for _ in range(length) ) 

Usar la función random.choice () de Numpy.

 import numpy as np import string if __name__ == '__main__': length = 16 a = np.random.choice(list(string.ascii_uppercase + string.digits), length) print(''.join(a)) 

La documentación está aquí http://docs.scipy.org/doc/numpy-1.10.0/reference/generated/numpy.random.choice.html

 >>> import string >>> import random 

La siguiente lógica todavía genera 6 caracteres de muestra aleatoria.

 >>> print ''.join(random.sample((string.ascii_uppercase+string.digits),6)) JT7K3Q 

No es necesario multiplicar por 6.

 >>> print ''.join(random.sample((string.ascii_uppercase+string.digits)*6,6)) TK82HK 

Para aquellos de ustedes que disfrutan de la python funcional:

 from itertools import imap, starmap, islice, repeat from functools import partial from string import letters, digits, join from random import choice join_chars = partial(join, sep='') identity = lambda o: o def irand_seqs(symbols=join_chars((letters, digits)), length=6, join=join_chars, select=choice, breakup=islice): """ Generates an indefinite sequence of joined random symbols each of a specific length :param symbols: symbols to select, [defaults to string.letters + string.digits, digits 0 - 9, lower and upper case English letters.] :param length: the length of each sequence, [defaults to 6] :param join: method used to join selected symbol, [defaults to ''.join generating a string.] :param select: method used to select a random element from the giving population. [defaults to random.choice, which selects a single element randomly] :return: indefinite iterator generating random sequences of giving [:param length] >>> from tools import irand_seqs >>> strings = irand_seqs() >>> a = next(strings) >>> assert isinstance(a, (str, unicode)) >>> assert len(a) == 6 >>> assert next(strings) != next(strings) """ return imap(join, starmap(breakup, repeat((imap(select, repeat(symbols)), None, length)))) 

Genera un iterador [infinito] indefinido, de secuencias aleatorias unidas, generando primero una secuencia indefinida de símbolo seleccionado al azar desde el conjunto que da, luego dividiendo esta secuencia en partes de longitud que luego se unen, debe funcionar con cualquier secuencia que admita getitem Por defecto, simplemente genera una secuencia aleatoria de letras alfanuméricas, aunque puede modificarla fácilmente para generar otras cosas:

por ejemplo para generar tuplas aleatorias de dígitos:

 >>> irand_tuples = irand_seqs(xrange(10), join=tuple) >>> next(irand_tuples) (0, 5, 5, 7, 2, 8) >>> next(irand_tuples) (3, 2, 2, 0, 3, 1) 

Si no quiere usar Next for Generation, simplemente puede hacerlo llamable:

 >>> irand_tuples = irand_seqs(xrange(10), join=tuple) >>> make_rand_tuples = partial(next, irand_tuples) >>> make_rand_tuples() (1, 6, 2, 8, 1, 9) 

Si desea generar la secuencia sobre la marcha, simplemente establezca unión a identidad.

 >>> irand_tuples = irand_seqs(xrange(10), join=identity) >>> selections = next(irand_tuples) >>> next(selections) 8 >>> list(selections) [6, 3, 8, 2, 2] 

Como otros han mencionado, si necesita más seguridad, configure la función de selección apropiada:

 >>> from random import SystemRandom >>> rand_strs = irand_seqs(select=SystemRandom().choice) 'QsaDxQ' 

el selector predeterminado es la choice que puede seleccionar el mismo símbolo varias veces para cada fragmento, si en su lugar desea seleccionar el mismo miembro como máximo una vez para cada fragmento, entonces, un posible uso:

 >>> from random import sample >>> irand_samples = irand_seqs(xrange(10), length=1, join=next, select=lambda pool: sample(pool, 6)) >>> next(irand_samples) [0, 9, 2, 3, 1, 6] 

usamos sample como nuestro selector, para hacer la selección completa, por lo que los trozos son en realidad longitud 1, y para unirlos simplemente llamamos a next que busca el siguiente trozo completamente generado, dado que este ejemplo parece un poco engorroso y es …

(1) Esto te dará todas las mayúsculas y números:

 import string, random passkey='' for x in range(8): if random.choice([1,2]) == 1: passkey += passkey.join(random.choice(string.ascii_uppercase)) else: passkey += passkey.join(random.choice(string.digits)) print passkey 

(2) Si más adelante desea incluir letras minúsculas en su clave, esto también funcionará:

 import string, random passkey='' for x in range(8): if random.choice([1,2]) == 1: passkey += passkey.join(random.choice(string.ascii_letters)) else: passkey += passkey.join(random.choice(string.digits)) print passkey 

Esta es una opinión sobre la respuesta de Anurag Uniyal y algo en lo que estuve trabajando en mí mismo.

 import random import string oneFile = open('‪Numbers.txt', 'w') userInput = 0 key_count = 0 value_count = 0 chars = string.ascii_uppercase + string.digits + string.punctuation for userInput in range(int(input('How many 12 digit keys do you want?'))): while key_count <= userInput: key_count += 1 number = random.randint(1, 999) key = number text = str(key) + ": " + str(''.join(random.sample(chars*6, 12))) oneFile.write(text + "\n") oneFile.close() 
 import string from random import * characters = string.ascii_letters + string.punctuation + string.digits password = "".join(choice(characters) for x in range(randint(8, 16))) print password 
 import random q=2 o=1 list =[r'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','s','0','1','2','3','4','5','6','7','8','9','0'] while(q>o): print("") for i in range(1,128): x=random.choice(list) print(x,end="") 

Aquí se puede cambiar la longitud de la cadena en el bucle for, es decir, para i en el rango (1, longitud) Es un algoritmo simple que es fácil de entender. Utiliza la lista para que pueda descartar los caracteres que no necesita.

 >>> import random >>> str = [] >>> chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890' >>> num = int(raw_input('How long do you want the string to be? ')) How long do you want the string to be? 10 >>> for k in range(1, num+1): ... str.append(random.choice(chars)) ... >>> str = "".join(str) >>> str 'tm2JUQ04CK' 

La función random.choice elige una entrada aleatoria en una lista. También crea una lista para que pueda agregar el carácter en la statement for . Al final de la secuencia está [‘t’, ‘m’, ‘2’, ‘J’, ‘U’, ‘Q’, ‘0’, ‘4’, ‘C’, ‘K’], pero la str = "".join(str) se encarga de eso, dejándole con 'tm2JUQ04CK' .

¡Espero que esto ayude!

Una simple:

 import string import random character = string.lowercase + string.uppercase + string.digits + string.punctuation char_len = len(character) # you can specify your password length here pass_len = random.randint(10,20) password = '' for x in range(pass_len): password = password + character[random.randint(0,char_len-1)] print password 

Me gustaría sugerirle la siguiente opción:

 import crypt n = 10 crypt.crypt("any sring").replace('/', '').replace('.', '').upper()[-n:-1] 

Modo paranoico:

 import uuid import crypt n = 10 crypt.crypt(str(uuid.uuid4())).replace('/', '').replace('.', '').upper()[-n:-1] 

Dos métodos:

 import random, math 

 def randStr_1(chars:str, length:int) -> str: chars *= math.ceil(length / len(chars)) chars = letters[0:length] chars = list(chars) random.shuffle(characters) return ''.join(chars) 

 def randStr_2(chars:str, length:int) -> str: return ''.join(random.choice(chars) for i in range(chars)) 

Punto de referencia:

 from timeit import timeit setup = """ import os, subprocess, time, string, random, math def randStr_1(letters:str, length:int) -> str: letters *= math.ceil(length / len(letters)) letters = letters[0:length] letters = list(letters) random.shuffle(letters) return ''.join(letters) def randStr_2(letters:str, length:int) -> str: return ''.join(random.choice(letters) for i in range(length)) """ print('Method 1 vs Method 2', ', run 10 times each.') for length in [100,1000,10000,50000,100000,500000,1000000]: print(length, 'characters:') eff1 = timeit("randStr_1(string.ascii_letters, {})".format(length), setup=setup, number=10) eff2 = timeit("randStr_2(string.ascii_letters, {})".format(length), setup=setup, number=10) print('\t{}s : {}s'.format(round(eff1, 6), round(eff2, 6))) print('\tratio = {} : {}\n'.format(eff1/eff1, round(eff2/eff1, 2))) 

Salida:

 Method 1 vs Method 2 , run 10 times each. 100 characters: 0.001411s : 0.00179s ratio = 1.0 : 1.27 1000 characters: 0.013857s : 0.017603s ratio = 1.0 : 1.27 10000 characters: 0.13426s : 0.151169s ratio = 1.0 : 1.13 50000 characters: 0.709403s : 0.855136s ratio = 1.0 : 1.21 100000 characters: 1.360735s : 1.674584s ratio = 1.0 : 1.23 500000 characters: 6.754923s : 7.160508s ratio = 1.0 : 1.06 1000000 characters: 11.232965s : 14.223914s ratio = 1.0 : 1.27 

El rendimiento del primer método es mejor.

para python 3 import string, random

” .join (random.choice (string.ascii_lowercase + string.ascii_uppercase + string.digits) para _ en el rango (15))

He ido a través de casi todas las respuestas, pero ninguna de ellas parece más fácil. Le sugiero que pruebe la biblioteca de passgen que generalmente se utiliza para crear contraseñas aleatorias.

Puede generar cadenas aleatorias de su elección de longitud, puntuación, dígitos, letras y mayúsculas.

Aquí está el código para su caso:

 from passgen import passgen string_length = int(input()) random_string = passgen(length=string_length, punctuation=False, digits=True, letters=True, case='upper') 

Encontré que esto es más simple y más limpio.

 str_Key = "" str_FullKey = "" str_CharacterPool = "01234ABCDEFfghij~>()" for int_I in range(64): str_Key = random.choice(str_CharacterPool) str_FullKey = str_FullKey + str_Key 

Simplemente cambia el 64 para variar la longitud, cambia CharacterPool para hacer solo alfa alfanumérico o numérico o solo caracteres extraños o lo que quieras.

Puedes usar el código

 var chars = "ABC123"; var random = new Random(); var result = new string( Enumerable.Repeat(chars, 7) //Change 7 to any number of characters you want in your outcome .Select(s => s[random.Next(s.Length)]) .ToArray()); textBox1.Text = result; 

Esto escupirá aleatoriamente un patrón alfanumérico al azar de 7, simplemente cambie el 7 a cualquier número que desee y producirá tantos números y / o letras.

Otra forma de escribir esto es la siguiente …

 var chars = "ABC123"; var stringChars = new char[7]; //Change 7 to any number of characters you want in your outcome var random = new Random(); for (int i = 0; i < stringChars.Length; i++) { stringChars[i] = chars[random.Next(chars.Length)]; } var finalString = new String(stringChars); textBox1.Text = finalstring;` 

No estoy seguro de cómo agregar restricciones tales como llegar a un lugar donde no permita que ciertos números y / o letras estén uno al lado del otro o repetir como obtener "AAA123" si alguien sabe cómo restringir el resultado para que tenga algo como esto por favor comenta de nuevo