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 ?
Quiero generar una cadena de tamaño N.
Debe estar compuesto de números y letras mayúsculas en inglés como:
¿Cómo puedo lograr esto de una manera pitónica ?
Respuestas:
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 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 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_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:
>>> 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 size
personajes. 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'
range
con xrange
.
random
con random.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:
''.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.choice
lugar de random.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 :
''.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 .
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.urandom
string.uppercase
que puede conducir a resultados inesperados dependiendo del conjunto de configuraciones regionales. Usar string.ascii_uppercase
(o string.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 de range
que la última genere una lista en memoria, mientras que la primera crea un iterador.
Si los UUID están bien para sus propósitos, use el uuid incorporado paquete .
import uuid; uuid.uuid4().hex.upper()[0:6]
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
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 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
sample
que nunca obtendrás el mismo personaje enumerado dos veces. También, por supuesto, fallará por N
más que 36
.
import uuid
lowercase_str = uuid.uuid4().hex
lowercase_str
es un valor aleatorio como 'cea8b32e00934aaea8c005a35d85a5c0'
uppercase_str = lowercase_str.upper()
uppercase_str
es 'CEA8B32E00934AAEA8C005A35D85A5C0'
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:
>>> 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).
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:
pip install StringGenerator
Divulgación: soy el autor del módulo strgen.
A partir de Python 3.6, debe usar el secrets
módulo si necesita que sea criptográficamente seguro en lugar del random
mó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.join
que usar una expresión generadora!
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.
N
.
Si necesita una cadena aleatoria en lugar de una pseudoaleatoria , debe usarla os.urandom
como 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))
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:
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))], "")
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 //
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) )
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
>>> 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
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 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:
>>> 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 unirnos simplemente llamamos next
qué recupera el siguiente trozo completamente generado, dado que este ejemplo parece un poco engorroso y es ...
(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
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()
>>> 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.choice
función selecciona una entrada aleatoria en una lista. También crea una lista para que pueda agregar el carácter en la for
declaració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!
range(num)
lugar, y str podría haber sido una cadena str += random.choice(chars)
.
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í, 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.
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
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.
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')
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'))
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
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.