Geração aleatória de cadeias com letras maiúsculas e dígitos


1336

Eu quero gerar uma sequência de tamanho N.

Deve ser composto por números e letras maiúsculas em inglês, como:

  • 6U1S75
  • 4Z4UKK
  • U911K4

Como posso conseguir isso de maneira pitônica ?


11
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
Blixt

1
@ Bufer, você estaria interessado nesta resposta então.
Anish Ramaswamy

Isso não deve ser renomeado "Geração aleatória de cadeias criptograficamente segura ..." ?
smci 9/09/18

Respostas:


2542

Responda em uma linha:

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

ou ainda mais curto a partir do Python 3.6 usando random.choices():

''.join(random.choices(string.ascii_uppercase + string.digits, k=N))

Uma versão criptograficamente mais segura; consulte https://stackoverflow.com/a/23728630/2213647 :

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

Em detalhes, com uma função limpa para reutilização adicional:

>>> 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 stringum módulo que contém sequências de caracteres ASCII comuns e randomum 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:

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

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:

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

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'

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

Os documentos do módulo também discutem maneiras convenientes de gerar tokens seguros e práticas recomendadas .


3
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

14
+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


8
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'


2
uppercase_str[:N+1]
Yajo

@Yajo sim podemos limitar usando corte
Savad KP

2
@ 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:

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

Obtenha uma lista exclusiva:

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

Garanta um caractere "especial" na string:

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

Uma cor HTML aleatória:

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

etc.

Precisamos estar cientes de que isso:

''.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.

Está no PyPI:

pip install StringGenerator

Divulgação: sou o autor do módulo strgen.


12

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!



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

3
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))], "")

4
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 >> 5
    return  ''.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:

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

... 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 //


5

Eu faria assim:

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

Ou apenas:

def rand_string(length, char_set=legals):

    return ''.join( random.choice(char_set) for _ in range(length) )

5

Use a função 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))

A documentação está aqui http://docs.scipy.org/doc/numpy-1.10.0/reference/generated/numpy.random.choice.html


1
Por que devo usar numpy random em vez de python stdlib random?
Pax0r

Porque permite mais opções em argumentos como comprimento, probabilidade variável e seleção com substituição.
Mudit Jain 11/07/16

5

Às vezes 0 (zero) e O (letra O) podem ser confusos. Então eu uso

import uuid
uuid.uuid4().hex[:6].upper().replace('0','X').replace('O','Y')

4
>>> import string 
>>> import random

a lógica a seguir ainda gera amostra aleatória de 6 caracteres

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

Não há necessidade de multiplicar por 6

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

TK82HK

3
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:

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

se você não quiser usar a próxima geração, poderá simplesmente torná-lo acessível:

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

se você deseja gerar a sequência em tempo real, basta definir junção à identidade.

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

Como já mencionado, se você precisar de mais segurança, defina a função de seleção apropriada:

>>> from random import SystemRandom
>>> 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:

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

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


3

(1) Isso fornecerá todos os limites e 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) 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  

3

esta é uma opinião sobre a resposta de Anurag Uniyal e algo que eu estava trabalhando comigo mesmo.

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

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

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'.

Espero que isto ajude!


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

2
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.


1

Um simples:

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

0

Gostaria de sugerir a próxima opção:

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

Modo paranóico:

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

0

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


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 :

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

O desempenho do primeiro método é melhor.


0

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:

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

0

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


0

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.


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

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

print(rand_pass())
# @5U,@A4yIZvnp%51

-2

Eu achei isso mais simples e limpo.

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 

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.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.