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

1337

Quiero generar una cadena de tamaño N.

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

  • 6U1S75
  • 4Z4UKK
  • U911K4

¿Cómo puedo lograr esto de una manera pitónica ?

Hellnar
fuente
11
Esta es una pregunta muy popular. Deseo que un experto agregue su opinión sobre la unicidad de estos números aleatorios para las 3 respuestas principales, es decir, la probabilidad de colisión para el rango del tamaño de la cadena, digamos de 6 a 16.
usuario
8
@buffer Es fácil calcular el número de combinaciones posibles. 10 números + 26 letras = 36 caracteres posibles, a la potencia de 6 (longitud de la cadena) es igual a aproximadamente dos mil millones. Mi regla general para los valores aleatorios es "si genero valores para cada humano en la Tierra, ¿cuántos valores podrían tener cada uno?". En este caso, sería menos de un valor por persona, por lo que si se trata de identificar usuarios u objetos, son muy pocos caracteres. Una alternativa sería agregar letras minúsculas, lo que lo ubica en 62 ^ 6 = casi 57 mil millones de valores únicos.
Blixt
1
Y si bien puede parecer una tontería pensar en la población mundial, es solo porque quieres un gran amortiguador para posibles colisiones. Vea el problema del cumpleaños: en.wikipedia.org/wiki/Birthday_problem
Blixt
1
@buffer, entonces te interesaría esta respuesta .
Anish Ramaswamy
¿No debería llamarse esto "Generación de cadenas aleatorias criptográficamente seguras ..." ?
smci

Respuestas:

2544

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

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

En detalles, con una función limpia 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 stringun módulo que contiene secuencias de caracteres ASCII comunes y randomun 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 elementos 'n':

>>> 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 crear 'n' veces la cadena elem, le pediremos a Python que cree 'n' veces un carácter aleatorio, seleccionado de una secuencia de caracteres:

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

Por random.choice(chars) for _ in range(size)lo tanto, realmente está creando una secuencia de sizepersonajes. Personajes que se seleccionan al azar de 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 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
fuente
77
@jorelli: No es una lista de comprensión; Es una expresión generadora.
Ignacio Vazquez-Abrams
2
@joreilli: Agregué una nota rápida sobre esto en la respuesta y un enlace a una respuesta más detallada sobre iterable, comprensión de listas, generadores y, finalmente, la palabra clave de rendimiento.
e-satis el
1
Lo reemplazaría rangecon xrange.
Dr. Jan-Philip Gehrcke
1
Muy útil. Curiosamente, Django está utilizando este código para generar contraseñas y tokens CSRF. Aunque debería reemplazarlo randomcon random.SystemRandom(): github.com/django/django/blob/…
usuario
1
@ Chiel92, random.samplecrea muestras sin reemplazo, en otras palabras, sin la posibilidad de repetir caracteres, lo cual no está en los requisitos del OP. No creo que sea deseable para la mayoría de las aplicaciones.
ontólogo
557

Esta pregunta de desbordamiento de pila es el principal resultado 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 hacerlo de forma segura haciendo un pequeño cambio en el código anterior:

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

Utilizando random.SystemRandom() lugar de solo usos aleatorios / dev / urandom en máquinas * nix y CryptGenRandom()en Windows. Estos son PRNG criptográficamente seguros. Usar en random.choicelugar de random.SystemRandom().choiceuna 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 usar 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 mejores prácticas .

Randy Marsh
fuente
3
Sí, la biblioteca estándar oficial de randomha advertido esto: " Advertencia : los generadores pseudoaleatorios de este módulo no deben usarse con fines de seguridad. Utilice os.urandom () o SystemRandom si necesita un generador de números pseudoaleatorios criptográficamente seguro. " Aquí está la referencia: random.SystemRandom y os.urandom
lord63. j
44
Gran respuesta. Pequeña nota: lo cambió a lo string.uppercaseque puede conducir a resultados inesperados dependiendo del conjunto de configuraciones regionales. Usar string.ascii_uppercase(o string.ascii_letters + string.digitspara base62 en lugar de base36) es más seguro en los casos en que está involucrada la codificación.
Blixt
pequeña nota: mejor usarla en xrangelugar de rangeque la última genere una lista en memoria, mientras que la primera crea un iterador.
guyarad
2
¿La picadura aleatoria será siempre única? Quería usar una clave primaria.
shakthydoss
3
@shakthydoss: no. Puede devolver "AAA000", que es una cadena aleatoria, y luego "AAA000", que también es una cadena aleatoria. Debe agregar explícitamente una comprobación de unicidad.
usr2564301
189

Simplemente use el líquido incorporado de Python:

Si los UUID están bien para sus propósitos, use el uuid incorporado paquete .

Solución de una 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
Bijan
fuente
14
+1 Por pensar detrás de la pregunta. Quizás podría explicar brevemente la diferencia entre uuid1 y uuid4.
Thomas Ahle
1
Si hago uuid1 tres veces seguidas obtengo: d161fd16-ab0f-11e3-9314-00259073e4a8, d3535b56-ab0f-11e3-9314-00259073e4a8, d413be32-ab0f-11e3-9314-00259073e4a8, lo cual parece ser sospechoso los primeros 8 caracteres difieren y el resto son iguales). Este no es el caso con uuid4
Chase Roberts
99
uui1: genera un UUID a partir de una ID de host, número de secuencia y la hora actual. uuid4: genera un UUID aleatorio.
Bijan
77
Si desea omitir la conversión de cadenas y el reemplazo de guiones, puede llamar a my_uuid.get_hex () o uuid.uuid4 (). Get_hex () y devolverá una cadena generada desde el uuid que no tiene guiones.
dshap
8
¿Es una buena idea truncar un UUID? Dependiendo de cuán pequeño string_lengthsea, la probabilidad de colisión puede ser una preocupación.
usuario
44

Una forma más simple, más rápida pero un poco menos aleatoria es usar en random.samplelugar de elegir cada letra por separado. Si se permiten n repeticiones, amplíe su base aleatoria en 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 previene la reutilización de caracteres, multiplicando el tamaño del conjunto de caracteres hace posible múltiples repeticiones, pero aún son menos probables que en una elección puramente aleatoria. Si vamos por 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 personaje son las mismas que las probabilidades de obtener 'X' como el primer personaje En la implementación random.sample, las probabilidades de obtener 'X' como cualquier personaje posterior son solo 6/7 la posibilidad de obtenerlo como el primer personaje

Anurag Uniyal
fuente
8
De esta manera no está mal, pero no es tan aleatorio como seleccionar cada personaje por separado, ya sampleque nunca obtendrás el mismo personaje enumerado dos veces. También, por supuesto, fallará por Nmás que 36.
bobince
para el caso de uso dado (si no hay repetición está bien) diré que sigue siendo la mejor solución.
Anurag Uniyal
3
Uno de los ejemplos tiene una repetición, así que dudo que esté buscando no permitir las repeticiones.
Mark Byers
55
Si random.sample impide la reutilización de los caracteres, multiplicar el tamaño del conjunto de caracteres hace posible múltiples repeticiones , pero aún son menos probables que en una elección puramente aleatoria. Si vamos por 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 personaje son las mismas que las probabilidades de obtener 'X' como el primer personaje En la implementación random.sample, las probabilidades de obtener 'X' como cualquier personaje posterior son solo 5/6 de la posibilidad de obtenerlo como primer personaje.
pcurry
1
La posibilidad de que un personaje en particular se repita disminuye a medida que avanza por la cadena generada. Generando una cadena de 6 caracteres a partir de las 26 letras mayúsculas más 10 dígitos, eligiendo aleatoriamente cada carácter de forma independiente, cualquier cadena particular ocurre con frecuencia 1 / (36 ^ 6). La posibilidad de generar 'FU3WYE' y 'XXXXXX' es la misma. En la implementación de muestra, la posibilidad de generar 'XXXXXX' es (1 / (36 ^ 6)) * ((6/6) * (5/6) * (4/6) * (3/6) * (2 / 6) * (1/6)) debido a la función de no reemplazo de random.sample. 'XXXXXX' es 324 veces menos probable en la implementación de muestra.
pcurry
32
import uuid
lowercase_str = uuid.uuid4().hex  

lowercase_str es un valor aleatorio como 'cea8b32e00934aaea8c005a35d85a5c0'

uppercase_str = lowercase_str.upper()

uppercase_str es 'CEA8B32E00934AAEA8C005A35D85A5C0'

Savad KP
fuente
2
uppercase_str[:N+1]
Yajo
@Yajo, sí, podemos limitar el uso de rebanado
Savad KP
2
@Yajo: no, no quieres cortar el valor hexadecimal. Elimina la entropía en comparación con una secuencia completa de letras mayúsculas y dígitos. Quizás codifique en base32 el valor (entropía ligeramente reducida, de 36 ** n a 32 ** n, aún mejor que 16 ** n).
Martijn Pieters
19

Una forma más rápida, fácil y flexible de hacer esto es usar el strgenmódulo ( 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'

Obtenga una lista única:

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

Garantice un carácter "especial" en la cadena:

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

Un color HTML aleatorio:

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

etc.

Debemos 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).

strgenes más rápido en tiempo de desarrollador que cualquiera de las soluciones anteriores. La solución de Ignacio es el rendimiento en tiempo de ejecución más rápido y es la respuesta correcta utilizando la Biblioteca estándar de Python. Pero casi nunca lo usará de esa forma. Deberá usar SystemRandom (o respaldo si no está disponible), asegurarse de que los juegos de caracteres requeridos estén representados, usar unicode (o no), asegurarse de que las invocaciones sucesivas produzcan una cadena única, use un subconjunto de una de las clases de caracteres del módulo de cadena, etc. Todo esto requiere mucho más código que en las respuestas proporcionadas. Los diversos intentos 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.

Paul Wolf
fuente
12

A partir de Python 3.6, debe usar el secretsmódulo si necesita que sea criptográficamente seguro en lugar del randommódulo (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 comprensión de lista es más rápida en el caso de str.joinque usar una expresión generadora!

MSeifert
fuente
10

Basado en otra respuesta de desbordamiento de pila, 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.

Gubbi
fuente
1
Esto es bueno, aunque solo usará 'AF' y no 'A-Z'. Además, el código se vuelve un poco menos agradable cuando se parametriza N.
Thomas Ahle
9

Si necesita una cadena aleatoria en lugar de una pseudoaleatoria , debe usarla os.urandomcomo 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))
John La Rooy
fuente
3
¿Cómo os.urandomno es pseudoaleatorio? Podría estar utilizando un mejor algoritmo para generar números que sean más aleatorios, pero aún es seudoaleatorio.
Tyilo
@Tyilo, soy consciente de la diferencia entre /dev/randomy /dev/urandom. El problema es que se /dev/randombloquea cuando no hay suficiente entropía, lo que limita su utilidad. Por una vez, el pad /dev/urandom no es lo suficientemente bueno, pero creo que es mejor que el pseudoaleatorio aquí.
John La Rooy
1
Yo diría que ambos /dev/randomy /dev/urandomes pseudoaleatorio, pero podría depender de su definición.
Tyilo
9

Pensé que nadie había respondido esto todavía jajaja! Pero bueno, aquí está mi propio intento:

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))], "")
nemesisfixx
fuente
44
No voy a rechazar esto, pero creo que es demasiado complicado para una tarea tan simple. La expresión de retorno es un monstruo. Simple es mejor que complejo.
Carl Smith
12
@CarlSmith, es cierto que mi solución parece un poco exagerada para la tarea, pero estaba al tanto de las otras soluciones más simples, y solo deseaba encontrar una ruta alternativa a una buena respuesta. Sin libertad, la creatividad está en peligro, así que seguí adelante y la publiqué.
nemesisfixx
7

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 se basa en bit a bit y y el cambio es más rápido que generar un nuevo número aleatorio para cada personaje.

# 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 números de 5 bits 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 momento era:

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

... pero para 64 cadenas de caracteres, los randbits pierden;)

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.

editar: actualizado para adaptarse a la pregunta (solo mayúsculas y dígitos), y usar operadores bit a bit & y >> en lugar de% y //

Robar
fuente
5

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) )
Carl Smith
fuente
5

Use 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

Mudit Jain
fuente
1
¿Por qué debería usar numpy random en lugar de python stdlib random?
Pax0r
Porque permite más opciones en argumentos como longitud, probabilidad variable y selección con reemplazo.
Mudit Jain
5

Algunas veces 0 (cero) y O (letra O) pueden ser confusos. Entonces uso

import uuid
uuid.uuid4().hex[:6].upper().replace('0','X').replace('O','Y')
Aseem
fuente
4
>>> import string 
>>> import random

la siguiente lógica aún genera una muestra aleatoria de 6 caracteres

>>> 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
usuario128956
fuente
3
Pero esta variante obligará a todos los personajes a ser diferentes. Y no funcionará si N es más grande que len (string.ascii_uppercase + string.digits)
MarSoft
3

Para aquellos de ustedes que disfrutan de 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 indefinido [infinito], de secuencias aleatorias unidas, generando primero una secuencia indefinida de símbolo seleccionado aleatoriamente del grupo de donaciones, luego dividiendo esta secuencia en partes de longitud que luego se unen, debería funcionar con cualquier secuencia que admita getitem , de forma predeterminada, simplemente genera una secuencia aleatoria de letras alfanuméricas, aunque puede modificarlas 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 desea usar next for generation, simplemente puede hacerlo invocable:

>>> 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 configure unirse a la 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 adecuada:

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

el selector predeterminado es el choiceque puede seleccionar el mismo símbolo varias veces para cada fragmento, si en cambio desea que se seleccione 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 samplecomo nuestro selector, para hacer la selección completa, por lo que los trozos son en realidad longitud 1, y para unirnos simplemente llamamos nextqué recupera el siguiente trozo completamente generado, dado que este ejemplo parece un poco engorroso y es ...

Samy Vilar
fuente
3

(1) Esto le dará todos los topes 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 luego 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  
Jacob
fuente
3

Esta es una versión de la respuesta de Anurag Uniyal y algo en lo que estaba trabajando yo 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()
Stopit Donk
fuente
2
>>> 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 random.choicefunción selecciona una entrada aleatoria en una lista. También crea una lista para que pueda agregar el carácter en la fordeclaración. Al final str es ['t', 'm', '2', 'J', 'U', 'Q', '0', '4', 'C', 'K'], pero las str = "".join(str)tomas cuidar de que, dejándole con 'tm2JUQ04CK'.

¡Espero que esto ayude!

AJ Uppal
fuente
Bien, pero podrías haber usado en su range(num)lugar, y str podría haber sido una cadena str += random.choice(chars).
sashk
2
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
Natasha
fuente
2
Aunque este código puede responder la pregunta, proporcionar un contexto adicional sobre por qué y / o cómo responde la pregunta mejoraría significativamente su valor a largo plazo. Por favor, editar su respuesta a añadir un poco de explicación.
Toby Speight
2
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í, la longitud de la cadena se puede cambiar en for loop, es decir, para i en rango (1, longitud) Es un algoritmo simple que es fácil de entender. utiliza la lista para que pueda descartar caracteres que no necesita.

lawlie8
fuente
1

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
Adicto al alcohol
fuente
0

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]
mrvol
fuente
0

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))


Benchmark:

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.

Bi Ao
fuente
0

He revisado casi todas las respuestas, pero ninguna de ellas parece más fácil. Te sugiero que pruebes el passgen biblioteca de que generalmente se usa 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')
Jarvis
fuente
0

Genere una ID aleatoria de 16 bytes que contenga letras, dígitos, '_' y '-'

os.urandom(16).translate((f'{string.ascii_letters}{string.digits}-_'*4).encode('ascii'))

socketpair
fuente
0

Estaba mirando las diferentes respuestas y me tomé el tiempo de leer la documentación de los secretos.

El módulo de secretos se utiliza para generar números aleatorios criptográficamente fuertes adecuados para administrar datos como contraseñas, autenticación de cuentas, tokens de seguridad y secretos relacionados.

En particular, los secretos deben usarse con preferencia al generador de números pseudoaleatorio predeterminado en el módulo aleatorio, que está diseñado para modelar y simular, no para seguridad o criptografía.

Mirando más sobre lo que tiene para ofrecer, encontré una función muy útil si desea imitar una ID como las ID de Google Drive:

secrets.token_urlsafe ([nbytes = None])
Devuelve una cadena de texto aleatoria segura para URL, que contiene bytes aleatorios nbytes. El texto está codificado en Base64, por lo que, en promedio, cada byte produce aproximadamente 1.3 caracteres . Si nbytes es Ninguno o no se proporciona, se utiliza un valor predeterminado razonable.

Úselo de la siguiente manera:

import secrets
import math

def id_generator():
    id = secrets.token_urlsafe(math.floor(32 / 1.3))
    return id

print(id_generator())

Salida de una identificación de 32 caracteres de longitud:

joXR8dYbBDAHpVs5ci6iD-oIgPhkeQFk

Sé que esto es ligeramente diferente de la pregunta del OP, pero espero que aún sea útil para muchos que estaban buscando el mismo caso de uso que estaba buscando.

Antonin GAVREL
fuente
-1
import string, random
lower = string.ascii_lowercase
upper = string.ascii_uppercase
digits = string.digits
special = '!"£$%^&*.,@#/?'

def rand_pass(l=4, u=4, d=4, s=4):
    p = []
    [p.append(random.choice(lower)) for x in range(l)]
    [p.append(random.choice(upper)) for x in range(u)]
    [p.append(random.choice(digits)) for x in range(d)]
    [p.append(random.choice(special)) for x in range(s)]
    random.shuffle(p)
    return "".join(p)

print(rand_pass())
# @5U,@A4yIZvnp%51
CONvid19
fuente
-2

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 cambie el 64 para variar la longitud, varíe el grupo de caracteres para hacer solo alfa alfanumérico o solo numérico o caracteres extraños o lo que desee.

MT Head
fuente