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
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:
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'
@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.
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
+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
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'
@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:
''.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.
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!
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))
¿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))],"")
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 >>5return''.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:
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:
Como otros han mencionado si necesita más seguridad, configure la función de selección adecuada:
>>>from random importSystemRandom>>> 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:
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 ...
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
>>>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'.
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
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.
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
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:
Method1 vs Method2, run 10 times each.100 characters:0.001411s:0.00179s
ratio =1.0:1.271000 characters:0.013857s:0.017603s
ratio =1.0:1.2710000 characters:0.13426s:0.151169s
ratio =1.0:1.1350000 characters:0.709403s:0.855136s
ratio =1.0:1.21100000 characters:1.360735s:1.674584s
ratio =1.0:1.23500000 characters:6.754923s:7.160508s
ratio =1.0:1.061000000 characters:11.232965s:14.223914s
ratio =1.0:1.27
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.
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.
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
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.
Respuestas:
Responda en una línea:
o incluso más corto comenzando con Python 3.6 usando
random.choices()
:Una versión criptográficamente más segura; ver https://stackoverflow.com/a/23728630/2213647 :
En detalles, con una función limpia para su posterior reutilización:
Como funciona ?
Importamos
string
un módulo que contiene secuencias de caracteres ASCII comunes yrandom
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:Luego usamos una lista de comprensión para crear una lista de elementos 'n':
En el ejemplo anterior, usamos
[
para crear la lista, pero no lo hacemos en laid_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 crear 'n' veces la cadena
elem
, le pediremos a Python que cree 'n' veces un carácter aleatorio, seleccionado de una secuencia de caracteres:Por
random.choice(chars) for _ in range(size)
lo tanto, realmente está creando una secuencia desize
personajes. Personajes que se seleccionan al azar dechars
:Luego los unimos con una cadena vacía para que la secuencia se convierta en una cadena:
fuente
range
conxrange
.random
conrandom.SystemRandom()
: github.com/django/django/blob/…random.sample
crea 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.Esta pregunta de desbordamiento de pila es el principal resultado actual de Google para "Python de cadena aleatoria". La respuesta principal actual es:
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:
Utilizando
random.SystemRandom()
lugar de solo usos aleatorios / dev / urandom en máquinas * nix yCryptGenRandom()
en Windows. Estos son PRNG criptográficamente seguros. Usar enrandom.choice
lugar derandom.SystemRandom().choice
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 usar el nuevo módulo de secretos como se menciona en la respuesta de MSeifert :
Los documentos del módulo también analizan formas convenientes de generar tokens seguros y mejores prácticas .
fuente
random
ha 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.urandomstring.uppercase
que puede conducir a resultados inesperados dependiendo del conjunto de configuraciones regionales. Usarstring.ascii_uppercase
(ostring.ascii_letters + string.digits
para base62 en lugar de base36) es más seguro en los casos en que está involucrada la codificación.xrange
lugar derange
que la última genere una lista en memoria, mientras que la primera crea un iterador.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:
Si necesita exactamente su formato (por ejemplo, "6U1S75"), puede hacerlo así:
fuente
string_length
sea, la probabilidad de colisión puede ser una preocupación.Una forma más simple, más rápida pero un poco menos aleatoria es usar en
random.sample
lugar de elegir cada letra por separado. Si se permiten n repeticiones, amplíe su base aleatoria en n veces, por ejemploNota: 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
fuente
sample
que nunca obtendrás el mismo personaje enumerado dos veces. También, por supuesto, fallará porN
más que36
.lowercase_str
es un valor aleatorio como'cea8b32e00934aaea8c005a35d85a5c0'
uppercase_str
es'CEA8B32E00934AAEA8C005A35D85A5C0'
fuente
uppercase_str[:N+1]
Una forma más rápida, fácil y flexible de hacer esto es usar el
strgen
módulo (pip install StringGenerator
).Genere una cadena aleatoria de 6 caracteres con letras mayúsculas y dígitos:
Obtenga una lista única:
Garantice un carácter "especial" en la cadena:
Un color HTML aleatorio:
etc.
Debemos ser conscientes de que esto:
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 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:
Divulgación: soy el autor del módulo strgen.
fuente
A partir de Python 3.6, debe usar el
secrets
módulo si necesita que sea criptográficamente seguro en lugar delrandom
módulo (de lo contrario, esta respuesta es idéntica a la de @Ignacio Vazquez-Abrams):Una nota adicional: ¡una comprensión de lista es más rápida en el caso de
str.join
que usar una expresión generadora!fuente
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:
mucho mas rápido.
fuente
N
.Si necesita una cadena aleatoria en lugar de una pseudoaleatoria , debe usarla
os.urandom
como fuentefuente
os.urandom
no es pseudoaleatorio? Podría estar utilizando un mejor algoritmo para generar números que sean más aleatorios, pero aún es seudoaleatorio./dev/random
y/dev/urandom
. El problema es que se/dev/random
bloquea 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í./dev/random
y/dev/urandom
es pseudoaleatorio, pero podría depender de su definición.Pensé que nadie había respondido esto todavía jajaja! Pero bueno, aquí está mi propio intento:
fuente
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.
... 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:
... 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 //
fuente
Lo haría de esta manera:
O solo:
fuente
Use la función random.choice () de Numpy
La documentación está aquí http://docs.scipy.org/doc/numpy-1.10.0/reference/generated/numpy.random.choice.html
fuente
Algunas veces 0 (cero) y O (letra O) pueden ser confusos. Entonces uso
fuente
la siguiente lógica aún genera una muestra aleatoria de 6 caracteres
No es necesario multiplicar por 6
fuente
Para aquellos de ustedes que disfrutan de Python funcional:
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:
si no desea usar next for generation, simplemente puede hacerlo invocable:
si desea generar la secuencia sobre la marcha, simplemente configure unirse a la identidad.
Como otros han mencionado si necesita más seguridad, configure la función de selección adecuada:
el selector predeterminado es el
choice
que 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:usamos
sample
como nuestro selector, para hacer la selección completa, por lo que los trozos son en realidad longitud 1, y para unirnos simplemente llamamosnext
qué recupera el siguiente trozo completamente generado, dado que este ejemplo parece un poco engorroso y es ...fuente
(1) Esto le dará todos los topes y números:
(2) Si luego desea incluir letras minúsculas en su clave, esto también funcionará:
fuente
Esta es una versión de la respuesta de Anurag Uniyal y algo en lo que estaba trabajando yo mismo.
fuente
La
random.choice
función selecciona una entrada aleatoria en una lista. También crea una lista para que pueda agregar el carácter en lafor
declaración. Al final str es ['t', 'm', '2', 'J', 'U', 'Q', '0', '4', 'C', 'K'], pero lasstr = "".join(str)
tomas cuidar de que, dejándole con'tm2JUQ04CK'
.¡Espero que esto ayude!
fuente
range(num)
lugar, y str podría haber sido una cadenastr += random.choice(chars)
.fuente
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.
fuente
Una simple:
fuente
Me gustaría sugerirle la siguiente opción:
Modo paranoico:
fuente
Dos métodos:
Salida:
El rendimiento del primer método es mejor.
fuente
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:
fuente
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'))
fuente
Estaba mirando las diferentes respuestas y me tomé el tiempo de leer la documentación de los secretos.
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:
Úselo de la siguiente manera:
Salida de una identificación de 32 caracteres de longitud:
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.
fuente
fuente
Encontré que esto es más simple y más limpio.
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.
fuente