Esta é uma pergunta muito popular. Desejo um especialista gostaria de acrescentar sua opinião sobre a singularidade desses números aleatórios para o top 3 respostas ou seja, a probabilidade de colisão para a faixa de tamanho de cordas, digamos, de 6 a 16.
usuário
8
@buffer É fácil calcular o número de combinações possíveis. 10 números + 26 letras = 36 caracteres possíveis, com a potência de 6 (comprimento da corda) é igual a cerca de dois bilhões. Minha regra prática para valores aleatórios é "se eu gerasse valores para todos os seres humanos na Terra, quantos valores eles poderiam ter para cada um?". Nesse caso, isso seria menos de um valor por pessoa; portanto, para identificar usuários ou objetos, são poucos caracteres. Uma alternativa seria adicionar letras minúsculas, o que significa 62 ^ 6 = quase 57 bilhões de valores únicos.
Blixt
1
E embora possa parecer bobagem pensar na população do mundo, isso é apenas porque você deseja uma reserva enorme para possíveis colisões. Veja o problema do aniversário: en.wikipedia.org/wiki/Birthday_problem
Em seguida, usamos uma compreensão de lista para criar uma 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']
No exemplo acima, usamos [para criar a lista, mas não na id_generatorfunção, para que o Python não crie a lista na memória, mas gera os elementos rapidamente, um por um (mais sobre isso aqui ).
Em vez de pedir para criar 'n' vezes a string elem, pediremos ao Python para criar 'n' vezes um caractere aleatório, escolhido a partir de uma sequência de caracteres:
Portanto, random.choice(chars) for _ in range(size)realmente está criando uma sequência de sizecaracteres. Caracteres escolhidos aleatoriamente 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']
Depois, juntamos-os a uma string vazia para que a sequência se torne uma string:
>>>''.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: Não é uma lista de compreensão; é uma expressão geradora.
Ignacio Vazquez-Abrams
2
@ joreilli: adicionei uma nota rápida sobre isso na resposta e um link para uma resposta mais detalhada sobre iterável, compreensão de lista, geradores e, eventualmente, a palavra-chave yield.
e-satis
1
Eu substituiria rangepor xrange.
Dr. Jan-Philip Gehrcke
1
Muito útil. Curiosamente, o Django está usando esse trecho de código para gerar senhas e tokens CSRF. Embora você deva substituir randompor random.SystemRandom(): github.com/django/django/blob/…
user
1
@ Chiel92, random.samplecria amostras sem substituição, ou seja, sem a possibilidade de repetir caracteres, o que não está nos requisitos do OP. Eu não acho que isso seria desejável para a maioria dos aplicativos.
Ontologista
557
Esta questão do Stack Overflow é o principal resultado atual do Google para "string aleatória Python". A principal resposta atual é:
''.join(random.choice(string.ascii_uppercase + string.digits)for _ in range(N))
Este é um método excelente, mas o PRNG aleatoriamente não é criptograficamente seguro. Suponho que muitas pessoas pesquisando essa questão desejem gerar seqüências aleatórias para criptografia ou senhas. Você pode fazer isso com segurança, fazendo uma pequena alteração no código acima:
''.join(random.SystemRandom().choice(string.ascii_uppercase + string.digits)for _ in range(N))
Usar em random.SystemRandom()vez de apenas aleatoriamente usa / dev / urandom em máquinas * nix e CryptGenRandom()no Windows. Estes são PRNGs criptograficamente seguros. Usar em random.choicevez de random.SystemRandom().choiceem um aplicativo que requer um PRNG seguro pode ser potencialmente devastador e, dada a popularidade dessa pergunta, aposto que esse erro já foi cometido muitas vezes.
Se você estiver usando python3.6 ou superior, poderá usar o novo módulo de segredos , conforme mencionado na resposta do MSeifert :
''.join(secrets.choice(string.ascii_uppercase + string.digits)for _ in range(N))
Sim, a biblioteca padrão oficial da randomalertou isso: " Aviso : Os geradores pseudo-aleatórios deste módulo não devem ser usados para fins de segurança. Use os.urandom () ou SystemRandom se você precisar de um gerador de números pseudo-aleatórios criptograficamente seguro. " Aqui está a ref: random.SystemRandom e os.urandom
lord63. j
4
Ótima resposta. Nota pequena: você alterou para o string.uppercaseque pode levar a resultados inesperados, dependendo do conjunto de localidades. Usar string.ascii_uppercase(ou string.ascii_letters + string.digitspara base62 em vez de base36) é mais seguro nos casos em que a codificação está envolvida.
Blixt
pequena nota - melhor usar em xrangevez de rangea última gerar uma lista na memória, enquanto a primeira cria um iterador.
31416 guyarad
2
a picada aleatória será sempre única? eu queria usar uma chave primária.
shakthydoss
3
@shakthydoss: não. Pode retornar "AAA000", que é uma sequência aleatória, e o próximo "AAA000", que também é uma sequência aleatória. Você deve adicionar explicitamente uma verificação de exclusividade.
precisa saber é o seguinte
189
Basta usar o uuid interno do Python:
Se os UUIDs forem bons para seus propósitos, use o pacote uuid interno .
Solução de uma linha:
import uuid; uuid.uuid4().hex.upper()[0:6]
Versão detalhada:
Exemplo:
import uuid
uuid.uuid4()#uuid4 => full random uuid# Outputs something like: UUID('0172fc9a-1dac-4414-b88d-6b9a6feb91ea')
Se você precisar exatamente do seu formato (por exemplo, "6U1S75"), poderá fazer o seguinte:
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 por trás da pergunta. Talvez você possa explicar brevemente a diferença entre uuid1 e uuid4.
Thomas Ahle
1
Se eu fizer o uuid1 três vezes seguidas, recebo: d161fd16-ab0f-11e3-9314-00259073e4a8, d3535b56-ab0f-11e3-9314-00259073e4a8, d413be32-ab0f-11e3-9314-00259073e4a8 os 8 primeiros caracteres diferem e o restante é o mesmo). Este não é o caso com uuid4
Perseguição Roberts
9
uui1: Gere um UUID a partir de um ID do host, número de sequência e hora atual. uuid4: gera um UUID aleatório.
Bijan
7
Se você quiser pular a conversão de caracteres e a substituição de hífen, basta chamar my_uuid.get_hex () ou uuid.uuid4 (). Get_hex () e ele retornará uma string gerada a partir do uuid que não possui hífens.
precisa saber é
8
É uma boa ideia truncar um UUID? Dependendo de quão pequena string_lengthé, a probabilidade de colisão pode ser uma preocupação.
usuário
44
Uma maneira mais simples, mais rápida, mas um pouco menos aleatória, é usar em random.samplevez de escolher cada letra separadamente. Se n-repetições forem permitidas, amplie sua base aleatória em n vezes.
import random
import string
char_set = string.ascii_uppercase + string.digits
print''.join(random.sample(char_set*6,6))
Nota: random.sample impede a reutilização de caracteres, multiplicar o tamanho do conjunto de caracteres possibilita várias repetições, mas elas ainda são menos prováveis do que elas são uma escolha aleatória pura. Se optarmos por uma sequência de comprimento 6 e escolhermos 'X' como o primeiro caractere, no exemplo escolhido, as chances de obter 'X' para o segundo caractere serão as mesmas que as de obter 'X' como o primeiro caractere. Na implementação random.sample, as chances de obter 'X' como qualquer caractere subseqüente têm apenas 6/7 de chance de obtê-lo como o primeiro caractere
Dessa forma, não é ruim, mas não é tão aleatório quanto selecionar cada personagem separadamente, pois samplevocê nunca obterá o mesmo personagem listado duas vezes. Além disso, é claro que falhará por Nmais que 36.
22910
para o caso de uso especificado (se nenhuma repetição estiver correta), direi que ainda é a melhor solução.
Anurag Uniyal
3
Um dos exemplos tem uma repetição, por isso duvido que ele esteja tentando impedir repetições.
Mark Byers
5
Se a reutilização caráter impede random.sample, multiplicando o tamanho do conjunto de caracteres faz várias repetições possíveis , mas eles ainda são menos provável , então eles estão em uma escolha aleatória pura. Se escolhermos uma sequência de comprimento 6 e escolhermos 'X' como o primeiro caractere, no exemplo escolhido, as chances de obter 'X' para o segundo caractere serão as mesmas que as de obter 'X' como o primeiro caractere. Na implementação random.sample, as chances de obter 'X' como qualquer caractere subseqüente têm apenas 5/6 de chance de obtê-lo como o primeiro caractere.
pcurry
1
A chance de repetir um caractere específico diminui à medida que você se move pela string gerada. Gerando uma sequência de 6 caracteres das 26 letras maiúsculas mais 10 dígitos, escolhendo aleatoriamente cada caractere independentemente, qualquer sequência específica ocorre com a frequência 1 / (36 ^ 6). A chance de gerar 'FU3WYE' e 'XXXXXX' é a mesma. Na implementação de amostra, a chance de gerar 'XXXXXX' é (1 / (36 ^ 6)) * ((6/6) * (5/6) * (4/6) * (3/6) * (2 / 6) * (1/6)) devido ao recurso de não substituição do random.sample. 'XXXXXX' é 324 vezes menos provável na implementação de amostra.
pcurry
32
import uuid
lowercase_str = uuid.uuid4().hex
lowercase_str é um valor aleatório como 'cea8b32e00934aaea8c005a35d85a5c0'
uppercase_str = lowercase_str.upper()
uppercase_str é 'CEA8B32E00934AAEA8C005A35D85A5C0'
@ Yajo: não, você não quer cortar o valor hexadecimal. Você remove a entropia em comparação com uma sequência completa de letras maiúsculas e dígitos. Talvez codifique base32 o valor (entropia ligeiramente reduzida, de 36 ** n para 32 ** n, ainda melhor que 16 ** n).
Martijn Pieters
19
Uma maneira mais rápida, fácil e flexível de fazer isso é usar o strgenmódulo ( pip install StringGenerator).
Gere uma sequência aleatória de 6 caracteres com letras maiúsculas e dígitos:
''.join(random.choice(string.ascii_uppercase + string.digits)for _ in range(N))
pode não ter um dígito (ou caractere maiúsculo).
strgené mais rápido no tempo do desenvolvedor do que qualquer uma das soluções acima. A solução da Ignacio é o desempenho mais rápido em tempo de execução e é a resposta certa usando a Biblioteca Padrão do Python. Mas você quase nunca o utilizará dessa forma. Você deseja usar SystemRandom (ou fallback, se não estiver disponível), garantir que os conjuntos de caracteres necessários sejam representados, usar unicode (ou não), garantir que sucessivas invocações produzam uma cadeia exclusiva, usar um subconjunto de uma das classes de caracteres do módulo de cadeia, etc. Isso tudo requer muito mais código do que nas respostas fornecidas. As várias tentativas de generalizar uma solução têm limitações que o strgen resolve com maior brevidade e poder expressivo usando uma linguagem de modelo simples.
No Python 3.6 em diante, você deve usar o secretsmódulo se precisar que ele seja criptograficamente seguro em vez do randommódulo (caso contrário, essa resposta é idêntica à de @Ignacio Vazquez-Abrams):
from secrets import choice
import string
''.join([choice(string.ascii_uppercase + string.digits)for _ in range(N)])
Uma observação adicional: uma compreensão de lista é mais rápida no caso do str.joinque usar uma expressão geradora!
Isso é legal, embora ele use apenas 'AF' e não 'A-Z'. Além disso, o código fica um pouco menos agradável ao parametrizar N.
Thomas Ahle
9
Se você precisar de uma sequência aleatória em vez de uma pseudoaleatória , use os.urandomcomo fonte
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))
Como os.urandomnão é pseudo-aleatório? Pode estar usando um algoritmo melhor para gerar números mais aleatórios, mas ainda é pseudo-aleatório.
Tyilo
@ Tyilo, estou ciente da diferença entre /dev/randome /dev/urandom. O problema é que /dev/randombloqueia quando não há entropia suficiente, o que limita sua utilidade. Por um tempo/dev/urandom não é bom o suficiente, mas acho que é melhor do que pseudo-aleatório aqui.
John La Rooy
1
Eu diria que ambos /dev/randome /dev/urandomé pseudo-aleatório, mas pode depender da sua definição.
Tyilo
9
Eu pensei que ninguém tinha respondido isso ainda lol! Mas ei, aqui está o meu próprio exemplo:
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))],"")
Não vou votar isso, mas acho que é muito complicado para uma tarefa tão simples. A expressão de retorno é um monstro. Simples é melhor que complexo.
Carl Smith
12
@CarlSmith, é verdade que minha solução parece um pouco exagerada para a tarefa, mas eu estava ciente das outras soluções mais simples e só queria encontrar uma rota alternativa para uma boa resposta. Sem liberdade, a criatividade está em perigo, então fui em frente e publiquei.
Nemesisfixx
7
Esse método é um pouco mais rápido e um pouco mais irritante do que o método random.choice () que Ignacio postou.
Ele tira proveito da natureza dos algoritmos pseudoaleatórios, e os bancos em bit a bit e and shift são mais rápidos do que gerar um novo número aleatório para cada caractere.
# 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')
... crie um gerador que retire números de 5 bits de cada vez 0..31 até que nenhum seja deixado
... join () os resultados do gerador em um número aleatório com os bits certos
Com Timeit, para cadeias de caracteres de 32 caracteres, o tempo era:
Mas essa variante forçará todos os caracteres a serem diferentes. E isso não vai funcionar se N é maior que len (string.ascii_uppercase + string.digits)
MarSoft
3
Para aqueles que gostam 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))))
Ele gera um iterador [infinito] indefinido, de seqüências aleatórias unidas, primeiro gerando uma sequência indefinida de símbolo selecionado aleatoriamente a partir do pool de distribuição e, em seguida, dividindo essa sequência em partes de comprimento que são então unidas, deve funcionar com qualquer sequência que suporte getitem , por padrão, ele simplesmente gera uma sequência aleatória de letras alfanuméricas, embora você possa modificar facilmente para gerar outras coisas:
por exemplo, para gerar tuplas aleatórias de dígitos:
Como já mencionado, se você precisar de mais segurança, defina a função de seleção apropriada:
>>>from random importSystemRandom>>> rand_strs = irand_seqs(select=SystemRandom().choice)'QsaDxQ'
o seletor padrão é o choiceque pode selecionar o mesmo símbolo várias vezes para cada bloco, se você preferir o mesmo membro selecionado no máximo uma vez para cada bloco, um possível uso:
nós usamos sample como nosso seletor para fazer a seleção completa, de modo que os pedaços são na verdade o comprimento 1, e para juntar, simplesmente chamamos nextque busca o próximo pedaço completamente gerado, desde que este exemplo pareça um pouco complicado e seja ...
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) Se você desejar incluir posteriormente letras minúsculas em sua chave, isso também 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'
A random.choicefunção seleciona uma entrada aleatória em uma lista. Você também cria uma lista para poder acrescentar o caractere na fordeclaração. No final, str é ['t', 'm', '2', 'J', 'U', 'Q', '0', '4', 'C', 'K'], mas as str = "".join(str)tomadas cuide disso, deixando você com 'tm2JUQ04CK'.
Bom, mas você poderia ter usado range(num), e str poderia ter sido uma string 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
Embora esse código possa responder à pergunta, fornecer um contexto adicional a respeito de por que e / ou como responde à pergunta melhoraria significativamente seu valor a longo prazo. Por favor edite sua resposta para adicionar alguma explicação.
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="")
Aqui, o comprimento da string pode ser alterado no loop for, ou seja, no intervalo i (1, length). É um algoritmo simples e fácil de entender. ele usa a lista para que você possa descartar caracteres desnecessários.
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))
Referência:
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)))
Resultado :
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
Eu fui embora quase todas as respostas, mas nenhuma delas parece mais fácil. Eu sugiro que você tente o passgen biblioteca , que geralmente é usada para criar senhas aleatórias.
Você pode gerar seqüências aleatórias de sua escolha , como comprimento, pontuação, dígitos, letras e maiúsculas.
Eu estava olhando as diferentes respostas e tirei um tempo para ler a documentação dos segredos
O módulo secrets é usado para gerar números aleatórios criptograficamente fortes, adequados para gerenciar dados como senhas, autenticação de conta, tokens de segurança e segredos relacionados.
Em particular, os segredos devem ser usados de preferência ao gerador de números pseudo-aleatórios padrão no módulo aleatório, projetado para modelagem e simulação, não para segurança ou criptografia.
Analisando mais o que ele tem a oferecer, achei uma função muito útil se você deseja imitar um ID como os do Google Drive:
secrets.token_urlsafe ([nbytes = Nenhum])
Retorna uma cadeia de texto aleatória segura para URL, contendo nbytes de bytes aleatórios. O texto é codificado em Base64, portanto, em média, cada byte resulta em aproximadamente 1,3 caracteres . Se nbytes for Nenhum ou não for fornecido, um padrão razoável será usado.
Use da seguinte maneira:
import secrets
import math
def id_generator():
id = secrets.token_urlsafe(math.floor(32/1.3))return id
print(id_generator())
Crie um ID de comprimento de 32 caracteres:
joXR8dYbBDAHpVs5ci6iD-oIgPhkeQFk
Sei que isso é um pouco diferente da pergunta do OP, mas espero que ainda seja útil para muitos que estavam procurando o mesmo caso de uso que eu estava procurando.
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
Basta alterar o 64 para variar o comprimento, variar o CharacterPool para fazer apenas alfa caracteres numéricos alfa ou numéricos apenas ou estranhos ou o que você quiser.
Respostas:
Responda em uma linha:
ou ainda mais curto a partir do Python 3.6 usando
random.choices()
:Uma versão criptograficamente mais segura; consulte https://stackoverflow.com/a/23728630/2213647 :
Em detalhes, com uma função limpa para reutilização adicional:
Como funciona ?
Importamos
string
um módulo que contém sequências de caracteres ASCII comuns erandom
um módulo que trata de geração aleatória.string.ascii_uppercase + string.digits
concatena apenas a lista de caracteres que representam caracteres e dígitos ASCII maiúsculos:Em seguida, usamos uma compreensão de lista para criar uma lista de elementos 'n':
No exemplo acima, usamos
[
para criar a lista, mas não naid_generator
função, para que o Python não crie a lista na memória, mas gera os elementos rapidamente, um por um (mais sobre isso aqui ).Em vez de pedir para criar 'n' vezes a string
elem
, pediremos ao Python para criar 'n' vezes um caractere aleatório, escolhido a partir de uma sequência de caracteres:Portanto,
random.choice(chars) for _ in range(size)
realmente está criando uma sequência desize
caracteres. Caracteres escolhidos aleatoriamentechars
:Depois, juntamos-os a uma string vazia para que a sequência se torne uma string:
fonte
range
porxrange
.random
porrandom.SystemRandom()
: github.com/django/django/blob/…random.sample
cria amostras sem substituição, ou seja, sem a possibilidade de repetir caracteres, o que não está nos requisitos do OP. Eu não acho que isso seria desejável para a maioria dos aplicativos.Esta questão do Stack Overflow é o principal resultado atual do Google para "string aleatória Python". A principal resposta atual é:
Este é um método excelente, mas o PRNG aleatoriamente não é criptograficamente seguro. Suponho que muitas pessoas pesquisando essa questão desejem gerar seqüências aleatórias para criptografia ou senhas. Você pode fazer isso com segurança, fazendo uma pequena alteração no código acima:
Usar em
random.SystemRandom()
vez de apenas aleatoriamente usa / dev / urandom em máquinas * nix eCryptGenRandom()
no Windows. Estes são PRNGs criptograficamente seguros. Usar emrandom.choice
vez derandom.SystemRandom().choice
em um aplicativo que requer um PRNG seguro pode ser potencialmente devastador e, dada a popularidade dessa pergunta, aposto que esse erro já foi cometido muitas vezes.Se você estiver usando python3.6 ou superior, poderá usar o novo módulo de segredos , conforme mencionado na resposta do MSeifert :
Os documentos do módulo também discutem maneiras convenientes de gerar tokens seguros e práticas recomendadas .
fonte
random
alertou isso: " Aviso : Os geradores pseudo-aleatórios deste módulo não devem ser usados para fins de segurança. Use os.urandom () ou SystemRandom se você precisar de um gerador de números pseudo-aleatórios criptograficamente seguro. " Aqui está a ref: random.SystemRandom e os.urandomstring.uppercase
que pode levar a resultados inesperados, dependendo do conjunto de localidades. Usarstring.ascii_uppercase
(oustring.ascii_letters + string.digits
para base62 em vez de base36) é mais seguro nos casos em que a codificação está envolvida.xrange
vez derange
a última gerar uma lista na memória, enquanto a primeira cria um iterador.Basta usar o uuid interno do Python:
Se os UUIDs forem bons para seus propósitos, use o pacote uuid interno .
Solução de uma linha:
import uuid; uuid.uuid4().hex.upper()[0:6]
Versão detalhada:
Exemplo:
Se você precisar exatamente do seu formato (por exemplo, "6U1S75"), poderá fazer o seguinte:
fonte
string_length
é, a probabilidade de colisão pode ser uma preocupação.Uma maneira mais simples, mais rápida, mas um pouco menos aleatória, é usar em
random.sample
vez de escolher cada letra separadamente. Se n-repetições forem permitidas, amplie sua base aleatória em n vezes.Nota: random.sample impede a reutilização de caracteres, multiplicar o tamanho do conjunto de caracteres possibilita várias repetições, mas elas ainda são menos prováveis do que elas são uma escolha aleatória pura. Se optarmos por uma sequência de comprimento 6 e escolhermos 'X' como o primeiro caractere, no exemplo escolhido, as chances de obter 'X' para o segundo caractere serão as mesmas que as de obter 'X' como o primeiro caractere. Na implementação random.sample, as chances de obter 'X' como qualquer caractere subseqüente têm apenas 6/7 de chance de obtê-lo como o primeiro caractere
fonte
sample
você nunca obterá o mesmo personagem listado duas vezes. Além disso, é claro que falhará porN
mais que36
.lowercase_str
é um valor aleatório como'cea8b32e00934aaea8c005a35d85a5c0'
uppercase_str
é'CEA8B32E00934AAEA8C005A35D85A5C0'
fonte
uppercase_str[:N+1]
Uma maneira mais rápida, fácil e flexível de fazer isso é usar o
strgen
módulo (pip install StringGenerator
).Gere uma sequência aleatória de 6 caracteres com letras maiúsculas e dígitos:
Obtenha uma lista exclusiva:
Garanta um caractere "especial" na string:
Uma cor HTML aleatória:
etc.
Precisamos estar cientes de que isso:
pode não ter um dígito (ou caractere maiúsculo).
strgen
é mais rápido no tempo do desenvolvedor do que qualquer uma das soluções acima. A solução da Ignacio é o desempenho mais rápido em tempo de execução e é a resposta certa usando a Biblioteca Padrão do Python. Mas você quase nunca o utilizará dessa forma. Você deseja usar SystemRandom (ou fallback, se não estiver disponível), garantir que os conjuntos de caracteres necessários sejam representados, usar unicode (ou não), garantir que sucessivas invocações produzam uma cadeia exclusiva, usar um subconjunto de uma das classes de caracteres do módulo de cadeia, etc. Isso tudo requer muito mais código do que nas respostas fornecidas. As várias tentativas de generalizar uma solução têm limitações que o strgen resolve com maior brevidade e poder expressivo usando uma linguagem de modelo simples.Está no PyPI:
Divulgação: sou o autor do módulo strgen.
fonte
No Python 3.6 em diante, você deve usar o
secrets
módulo se precisar que ele seja criptograficamente seguro em vez dorandom
módulo (caso contrário, essa resposta é idêntica à de @Ignacio Vazquez-Abrams):Uma observação adicional: uma compreensão de lista é mais rápida no caso do
str.join
que usar uma expressão geradora!fonte
Com base em outra resposta do Stack Overflow, a maneira mais leve de criar uma sequência aleatória e um número hexadecimal aleatório , uma versão melhor que a resposta aceita seria:
muito mais rapido.
fonte
N
.Se você precisar de uma sequência aleatória em vez de uma pseudoaleatória , use
os.urandom
como fontefonte
os.urandom
não é pseudo-aleatório? Pode estar usando um algoritmo melhor para gerar números mais aleatórios, mas ainda é pseudo-aleatório./dev/random
e/dev/urandom
. O problema é que/dev/random
bloqueia quando não há entropia suficiente, o que limita sua utilidade. Por um tempo/dev/urandom
não é bom o suficiente, mas acho que é melhor do que pseudo-aleatório aqui./dev/random
e/dev/urandom
é pseudo-aleatório, mas pode depender da sua definição.Eu pensei que ninguém tinha respondido isso ainda lol! Mas ei, aqui está o meu próprio exemplo:
fonte
Esse método é um pouco mais rápido e um pouco mais irritante do que o método random.choice () que Ignacio postou.
Ele tira proveito da natureza dos algoritmos pseudoaleatórios, e os bancos em bit a bit e and shift são mais rápidos do que gerar um novo número aleatório para cada caractere.
... crie um gerador que retire números de 5 bits de cada vez 0..31 até que nenhum seja deixado
... join () os resultados do gerador em um número aleatório com os bits certos
Com Timeit, para cadeias de caracteres de 32 caracteres, o tempo era:
... mas para 64 cadeias de caracteres, randbits perde;)
Eu provavelmente nunca usaria essa abordagem no código de produção, a menos que realmente não gostasse dos meus colegas de trabalho.
edit: atualizado para se adequar à pergunta (somente maiúsculas e dígitos) e use operadores bit a bit & e >> em vez de% e //
fonte
Eu faria assim:
Ou apenas:
fonte
Use a função random.choice () de Numpy
A documentação está aqui http://docs.scipy.org/doc/numpy-1.10.0/reference/generated/numpy.random.choice.html
fonte
Às vezes 0 (zero) e O (letra O) podem ser confusos. Então eu uso
fonte
a lógica a seguir ainda gera amostra aleatória de 6 caracteres
Não há necessidade de multiplicar por 6
fonte
Para aqueles que gostam de python funcional:
Ele gera um iterador [infinito] indefinido, de seqüências aleatórias unidas, primeiro gerando uma sequência indefinida de símbolo selecionado aleatoriamente a partir do pool de distribuição e, em seguida, dividindo essa sequência em partes de comprimento que são então unidas, deve funcionar com qualquer sequência que suporte getitem , por padrão, ele simplesmente gera uma sequência aleatória de letras alfanuméricas, embora você possa modificar facilmente para gerar outras coisas:
por exemplo, para gerar tuplas aleatórias de dígitos:
se você não quiser usar a próxima geração, poderá simplesmente torná-lo acessível:
se você deseja gerar a sequência em tempo real, basta definir junção à identidade.
Como já mencionado, se você precisar de mais segurança, defina a função de seleção apropriada:
o seletor padrão é o
choice
que pode selecionar o mesmo símbolo várias vezes para cada bloco, se você preferir o mesmo membro selecionado no máximo uma vez para cada bloco, um possível uso:nós usamos
sample
como nosso seletor para fazer a seleção completa, de modo que os pedaços são na verdade o comprimento 1, e para juntar, simplesmente chamamosnext
que busca o próximo pedaço completamente gerado, desde que este exemplo pareça um pouco complicado e seja ...fonte
(1) Isso fornecerá todos os limites e números:
(2) Se você desejar incluir posteriormente letras minúsculas em sua chave, isso também funcionará:
fonte
esta é uma opinião sobre a resposta de Anurag Uniyal e algo que eu estava trabalhando comigo mesmo.
fonte
A
random.choice
função seleciona uma entrada aleatória em uma lista. Você também cria uma lista para poder acrescentar o caractere nafor
declaração. No final, str é ['t', 'm', '2', 'J', 'U', 'Q', '0', '4', 'C', 'K'], mas asstr = "".join(str)
tomadas cuide disso, deixando você com'tm2JUQ04CK'
.Espero que isto ajude!
fonte
range(num)
, e str poderia ter sido uma stringstr += random.choice(chars)
.fonte
Aqui, o comprimento da string pode ser alterado no loop for, ou seja, no intervalo i (1, length). É um algoritmo simples e fácil de entender. ele usa a lista para que você possa descartar caracteres desnecessários.
fonte
Um simples:
fonte
Gostaria de sugerir a próxima opção:
Modo paranóico:
fonte
Dois métodos:
Resultado :
O desempenho do primeiro método é melhor.
fonte
Eu fui embora quase todas as respostas, mas nenhuma delas parece mais fácil. Eu sugiro que você tente o passgen biblioteca , que geralmente é usada para criar senhas aleatórias.
Você pode gerar seqüências aleatórias de sua escolha , como comprimento, pontuação, dígitos, letras e maiúsculas.
Aqui está o código para o seu caso:
fonte
Gere uma ID aleatória de 16 bytes contendo letras, dígitos, '_' e '-'
os.urandom(16).translate((f'{string.ascii_letters}{string.digits}-_'*4).encode('ascii'))
fonte
Eu estava olhando as diferentes respostas e tirei um tempo para ler a documentação dos segredos
Analisando mais o que ele tem a oferecer, achei uma função muito útil se você deseja imitar um ID como os do Google Drive:
Use da seguinte maneira:
Crie um ID de comprimento de 32 caracteres:
Sei que isso é um pouco diferente da pergunta do OP, mas espero que ainda seja útil para muitos que estavam procurando o mesmo caso de uso que eu estava procurando.
fonte
fonte
Eu achei isso mais simples e limpo.
Basta alterar o 64 para variar o comprimento, variar o CharacterPool para fazer apenas alfa caracteres numéricos alfa ou numéricos apenas ou estranhos ou o que você quiser.
fonte