Generazione casuale di stringhe con lettere maiuscole e cifre


1336

Voglio generare una stringa di dimensioni N.

Dovrebbe essere composto da numeri e lettere inglesi maiuscole come:

  • 6U1S75
  • 4Z4UKK
  • U911K4

Come posso raggiungere questo obiettivo in modo pitonico ?


11
Questa è una domanda molto popolare. Vorrei che un esperto aggiungesse la sua opinione sull'unicità di questi numeri casuali per le prime 3 risposte, vale a dire la probabilità di collisione per un intervallo di dimensioni della stringa, diciamo da 6 a 16.
utente

8
@buffer È facile calcolare il numero di possibili combinazioni. 10 numeri + 26 lettere = 36 caratteri possibili, alla potenza di 6 (lunghezza della stringa) è pari a circa due miliardi. La mia regola empirica per i valori casuali è "se ho generato valori per ogni essere umano sulla Terra, quanti valori potrebbero avere ciascuno?". In questo caso sarebbe inferiore a un valore per persona, quindi se si tratta di identificare utenti o oggetti, è troppo pochi caratteri. Un'alternativa sarebbe quella di aggiungere lettere minuscole, che ti portano a 62 ^ 6 = quasi 57 miliardi di valori unici.
Blixt,

1
E mentre può sembrare sciocco pensare alla popolazione mondiale, è solo perché vuoi un enorme buffer per potenziali collisioni. Vedi il problema del compleanno: en.wikipedia.org/wiki/Birthday_problem
Blixt,

1
@buffer, allora saresti interessato a questa risposta .
Anish Ramaswamy,

Non dovrebbe essere rinominato "Generazione di stringhe casuali crittograficamente sicura ..." ?
smci,

Risposte:


2542

Risposta in una riga:

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

o anche più breve a partire da Python 3.6 usando random.choices():

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

Una versione crittograficamente più sicura; vedi https://stackoverflow.com/a/23728630/2213647 :

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

In dettaglio, con una funzione pulita per un ulteriore riutilizzo:

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

Come funziona ?

Importiamo stringun modulo che contiene sequenze di caratteri ASCII comuni e randomun modulo che si occupa della generazione casuale.

string.ascii_uppercase + string.digits concatena semplicemente l'elenco di caratteri che rappresentano caratteri e cifre ASCII maiuscoli:

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

Quindi usiamo una comprensione dell'elenco per creare un elenco di elementi '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']

Nell'esempio sopra, usiamo [per creare l'elenco, ma non facciamo parte della id_generatorfunzione, quindi Python non crea l'elenco in memoria, ma genera gli elementi al volo, uno per uno (ne parleremo di più qui ).

Invece di chiedere di creare 'n' volte la stringa elem , chiederemo a Python di creare 'n' volte un carattere casuale, scelto da una sequenza di caratteri:

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

Quindi random.choice(chars) for _ in range(size)sta davvero creando una sequenza di sizepersonaggi. Personaggi scelti a caso da 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']

Quindi li uniamo con una stringa vuota in modo che la sequenza diventi una stringa:

>>> ''.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: non è una comprensione dell'elenco; è un'espressione generatrice.
Ignacio Vazquez-Abrams,

2
@joreilli: ho aggiunto una breve nota al riguardo nella risposta e un collegamento a una risposta più dettagliata su iterabile, comprensione dell'elenco, generatori e infine la parola chiave di rendimento.
e-satis

1
Sostituirei rangecon xrange.
Dr. Jan-Philip Gehrcke,

1
Molto utile. È interessante notare che Django sta usando questo codice per generare password e token CSRF. Anche se è necessario sostituire randomcon random.SystemRandom(): github.com/django/django/blob/…
utente

1
@ Chiel92, random.samplecrea campioni senza sostituzione, in altre parole, senza la possibilità di ripetere i caratteri, cosa che non rientra nei requisiti del PO. Non penso che sarebbe auspicabile per la maggior parte delle applicazioni.
ontologo il

557

Questa domanda Stack Overflow è l'attuale risultato principale di Google per "Python stringa casuale". L'attuale risposta principale è:

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

Questo è un metodo eccellente, ma il PRNG in modo casuale non è sicuro dal punto di vista crittografico. Presumo che molte persone che ricercano questa domanda vorranno generare stringhe casuali per crittografia o password. Puoi farlo in modo sicuro apportando una piccola modifica nel codice sopra:

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

Usando random.SystemRandom()anziché semplicemente usi casuali / dev / urandom su macchine * nix e CryptGenRandom()in Windows. Questi sono PRNG crittograficamente sicuri. L'utilizzo random.choiceanziché random.SystemRandom().choicein un'applicazione che richiede un PRNG sicuro potrebbe essere potenzialmente devastante e, data la popolarità di questa domanda, scommetto che l'errore è già stato fatto molte volte.

Se stai usando python3.6 o successivo, puoi usare il nuovo modulo segreti come menzionato nella risposta di MSeifert :

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

I documenti del modulo discutono anche modi convenienti per generare token sicuri e best practice .


3
Sì, la libreria standard ufficiale per randomha avvertito questo: " Avvertenza : i generatori pseudo-casuali di questo modulo non devono essere usati per motivi di sicurezza. Utilizzare os.urandom () o SystemRandom se si necessita di un generatore di numeri pseudo-casuali sicuro crittograficamente. " Ecco l'arbitro: random.SystemRandom e os.urandom
lord63. j

4
Bella risposta. Piccola nota: è stato modificato in string.uppercasecui può portare a risultati imprevisti a seconda delle impostazioni locali. L'uso string.ascii_uppercase(o string.ascii_letters + string.digitsper base62 invece di base36) è più sicuro nei casi in cui è coinvolta la codifica.
Blixt,

piccola nota: è preferibile utilizzarlo xrangeanziché rangecome quest'ultimo genera un elenco in memoria, mentre il primo crea un iteratore.
Guyarad,

2
la puntura casuale sarà sempre unica? volevo usare una chiave primaria.
shakthydoss,

3
@shakthydoss: no. Potrebbe restituire "AAA000", che è una stringa casuale, e successivamente "AAA000", che è anche una stringa casuale. È necessario aggiungere esplicitamente un controllo per l'unicità.
usr2564301

189

Usa semplicemente il comando incorporato di Python:

Se gli UUID sono a posto per i tuoi scopi, usa il pacchetto uuid integrato .

Una soluzione di linea:

import uuid; uuid.uuid4().hex.upper()[0:6]

Nella versione approfondita:

Esempio:

import uuid
uuid.uuid4() #uuid4 => full random uuid
# Outputs something like: UUID('0172fc9a-1dac-4414-b88d-6b9a6feb91ea')

Se hai bisogno esattamente del tuo formato (ad esempio "6U1S75"), puoi farlo in questo modo:

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 Per pensare dietro la domanda. Forse potresti spiegare brevemente la differenza tra uuid1 e uuid4.
Thomas Ahle,

1
Se lo faccio uuid1 tre volte di seguito, ottengo: d161fd16-ab0f-11e3-9314-00259073e4a8, d3535b56-ab0f-11e3-9314-00259073e4a8, d413be32-ab0f-11e3-9314-00259073e4a8 i primi 8 caratteri differiscono e gli altri sono uguali). Questo non è il caso di uuid4
Chase Roberts,

9
uui1: genera un UUID da un ID host, un numero di sequenza e l'ora corrente. uuid4: genera un UUID casuale.
Bijan

7
Se vuoi saltare il casting della stringa e la sostituzione del trattino, puoi semplicemente chiamare my_uuid.get_hex () o uuid.uuid4 (). Get_hex () e restituirà una stringa generata dall'uuid che non ha trattini.
dshap

8
È una buona idea troncare un UUID? A seconda di quanto string_lengthè piccola , la probabilità di collisione può essere una preoccupazione.
utente

44

Un modo più semplice, più veloce ma leggermente meno casuale è usare random.sampleinvece di scegliere ciascuna lettera separatamente, se sono consentite n-ripetizioni, allarga la tua base casuale di n volte es.

import random
import string

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

Nota: random.sample impedisce il riutilizzo dei caratteri, la moltiplicazione delle dimensioni del set di caratteri rende possibili più ripetizioni, ma sono ancora meno probabili di essere in una scelta casuale. Se prendiamo una stringa di lunghezza 6 e scegliamo "X" come primo carattere, nell'esempio di scelta, le probabilità di ottenere "X" per il secondo carattere sono le stesse di quelle di ottenere "X" come primo personaggio. Nell'implementazione random.sample, le probabilità di ottenere 'X' come qualsiasi personaggio successivo sono solo 6/7 la possibilità di ottenerlo come primo personaggio


8
In questo modo non è male, ma non è così casuale come selezionare ogni personaggio separatamente, poiché samplenon avrai mai lo stesso personaggio elencato due volte. Inoltre ovviamente fallirà per un valore Nsuperiore a 36.
mercoledì

per il caso d'uso indicato (se nessuna ripetizione è ok), dirò che è ancora la soluzione migliore.
Anurag Uniyal,

3
Uno degli esempi ha una ripetizione, quindi dubito che stia cercando di non ripetere le ripetizioni.
Mark Byers,

5
Se random.sample impedisce il riutilizzo dei caratteri, la moltiplicazione delle dimensioni del set di caratteri rende possibili più ripetizioni , ma sono ancora meno probabili di essere in una scelta casuale. Se prendiamo una stringa di lunghezza 6 e scegliamo "X" come primo carattere, nell'esempio di scelta, le probabilità di ottenere "X" per il secondo carattere sono le stesse di quelle di ottenere "X" come primo personaggio. Nell'implementazione random.sample, le probabilità di ottenere 'X' come qualsiasi personaggio successivo hanno solo il 5/6 possibilità di ottenerlo come primo personaggio.
pcurry

1
La possibilità di ottenere un particolare personaggio ripetuto diminuisce mentre ci si sposta attraverso la stringa generata. Generando una stringa di 6 caratteri dalle 26 lettere maiuscole più 10 cifre, scegliendo casualmente ogni carattere in modo indipendente, ogni stringa particolare si presenta con frequenza 1 / (36 ^ 6). La possibilità di generare "FU3WYE" e "XXXXXX" è la stessa. Nell'implementazione del campione, la possibilità di generare 'XXXXXX' è (1 / (36 ^ 6)) * ((6/6) * (5/6) * (4/6) * (3/6) * (2 / 6) * (1/6)) a causa della funzione non sostitutiva di random.sample. 'XXXXXX' è 324 volte meno probabile nell'implementazione del campione.
pcurry

32
import uuid
lowercase_str = uuid.uuid4().hex  

lowercase_str è un valore casuale come 'cea8b32e00934aaea8c005a35d85a5c0'

uppercase_str = lowercase_str.upper()

uppercase_str è 'CEA8B32E00934AAEA8C005A35D85A5C0'


2
uppercase_str[:N+1]
Yajo,

@Yajo sì, possiamo limitare l'uso
dell'affettatura

2
@Yajo: no, non vuoi dividere il valore esadecimale. Si rimuove l'entropia rispetto a una sequenza completa di lettere maiuscole e cifre. Forse base32 codifica invece il valore (entropia leggermente ridotta, da 36 ** n a 32 ** n, ancora migliore di 16 ** n).
Martijn Pieters

19

Un modo più veloce, più facile e più flessibile per farlo è utilizzare il strgenmodulo (pip install StringGenerator ).

Genera una stringa casuale di 6 caratteri con lettere maiuscole e cifre:

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

Ottieni un elenco unico:

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

Garantire un carattere "speciale" nella stringa:

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

Un colore HTML casuale:

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

eccetera.

Dobbiamo essere consapevoli del fatto che questo:

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

potrebbe non contenere una cifra (o un carattere maiuscolo).

strgenè più veloce nel tempo degli sviluppatori rispetto a una qualsiasi delle soluzioni precedenti. La soluzione di Ignacio offre le prestazioni di runtime più veloci ed è la risposta giusta utilizzando la libreria standard Python. Ma non lo userai quasi mai in quella forma. Dovrai utilizzare SystemRandom (o fallback se non disponibile), assicurarti che i set di caratteri richiesti siano rappresentati, utilizzare unicode (o meno), assicurarti che le chiamate successive producano una stringa univoca, usi un sottoinsieme di una delle classi di caratteri del modulo stringa, ecc. Tutto ciò richiede molto più codice rispetto alle risposte fornite. I vari tentativi di generalizzare una soluzione hanno tutti dei limiti che strgen risolve con maggiore brevità e potenza espressiva usando un semplice linguaggio di template.

È su PyPI:

pip install StringGenerator

Divulgazione: sono l'autore del modulo strgen.


12

Da Python 3.6 in poi dovresti usare il secretsmodulo se ne hai bisogno per essere crittograficamente sicuro al posto del randommodulo (altrimenti questa risposta è identica a quella di @Ignacio Vazquez-Abrams):

from secrets import choice
import string

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

Un'ulteriore nota: una comprensione dell'elenco è più rapida nel caso str.joinrispetto all'uso di un'espressione del generatore!



9

Se hai bisogno di una stringa casuale anziché di una pseudo casuale , dovresti usare os.urandomcome sorgente

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
Come os.urandomnon è pseudo casuale? Potrebbe utilizzare un algoritmo migliore per generare numeri più casuali, ma è ancora pseudo casuale.
Tyilo,

@Tyilo, sono consapevole della differenza tra /dev/randome /dev/urandom. Il problema è che si /dev/randomblocca quando non c'è abbastanza entropia che ne limita l'utilità. Per una volta il pad /dev/urandom non è abbastanza buono, ma penso che sia meglio dello pseudo random qui.
John La Rooy,

1
Direi che sia /dev/randome /dev/urandomsia pseudo casuale, ma potrebbe dipendere dalla vostra definizione.
Tyilo,

9

Pensavo che nessuno avesse ancora risposto a questo lol! Ma hey, ecco la mia prova:

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
Non lo voterò, ma penso che sia troppo complicato per un compito così semplice. L'espressione di ritorno è un mostro. Semplice è meglio di complesso.
Carl Smith,

12
@CarlSmith, vero la mia soluzione sembra un po 'eccessiva per l'attività, ma ero a conoscenza delle altre soluzioni più semplici e volevo solo trovare una strada alternativa per una buona risposta. Senza libertà, la creatività è in pericolo, quindi sono andato avanti e l'ho pubblicato.
nemesisfixx il

7

Questo metodo è leggermente più veloce e leggermente più fastidioso rispetto al metodo random.choice () pubblicato da Ignacio.

Sfrutta la natura degli algoritmi pseudo-casuali e i banchi su bit per bit e spostamento sono più veloci rispetto alla generazione di un nuovo numero casuale per ciascun personaggio.

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

... crea un generatore che elimina i numeri di 5 bit alla volta 0..31 fino a quando nessuno se ne è andato

... unisci () i risultati del generatore su un numero casuale con i bit giusti

Con Timeit, per stringhe di 32 caratteri, il tempismo era:

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

... ma per 64 stringhe di caratteri, perde il randbit;)

Probabilmente non userei mai questo approccio nel codice di produzione se non mi piacessero davvero i miei colleghi.

modifica: aggiornato per adattarsi alla domanda (solo lettere maiuscole e cifre) e utilizzare operatori bit per bit & e >> invece di% e //


5

Lo farei così:

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

def rand_string(length, char_set=legals):

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

5

Usa la funzione random.choice () di 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 documentazione è qui http://docs.scipy.org/doc/numpy-1.10.0/reference/generated/numpy.random.choice.html


1
Perché dovrei usare numpy random invece di python stdlib random?
Pax0r,

Perché consente più opzioni in argomenti come lunghezza, probabilità variabile e selezione con sostituzione.
Mudit Jain,

5

A volte 0 (zero) e O (lettera O) possono creare confusione. Quindi io uso

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

4
>>> import string 
>>> import random

la seguente logica genera ancora un campione casuale di 6 caratteri

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

Non è necessario moltiplicare per 6

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

TK82HK

3
Ma questa variante costringerà tutti i personaggi a essere diversi. E non funzionerà se N è più grande di len (string.ascii_uppercase + string.digits)
MarSoft

3

Per quelli di voi che amano il pitone funzionale:

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 iteratore indefinito [infinito], di sequenze casuali unite, generando dapprima una sequenza indefinita di simboli scelti casualmente dal pool di assegnazione, quindi spezzando questa sequenza in parti di lunghezza che vengono poi unite, dovrebbe funzionare con qualsiasi sequenza che supporti getitem , per impostazione predefinita genera semplicemente una sequenza casuale di lettere alfanumeriche, sebbene sia possibile modificarle facilmente per generare altre cose:

per esempio per generare tuple casuali di cifre:

>>> 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 non vuoi usare la prossima generazione, puoi semplicemente renderla richiamabile:

>>> 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 si desidera generare la sequenza al volo, impostare semplicemente join su identità.

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

Come altri hanno già detto se hai bisogno di maggiore sicurezza, imposta la funzione di selezione appropriata:

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

il selettore predefinito è choiceche può selezionare più volte lo stesso simbolo per ogni blocco, se invece si desidera selezionare lo stesso membro al massimo una volta per ciascun blocco, un possibile utilizzo:

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

usiamo samplecome nostro selettore, per fare la selezione completa, quindi i blocchi sono effettivamente di lunghezza 1, e per unirci chiamiamo semplicemente nextche recupera il prossimo pezzo completamente generato, dato che questo esempio sembra un po 'ingombrante ed è ...


3

(1) Questo ti darà tutti i tappi e i numeri:

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 in seguito desideri includere lettere minuscole nella tua chiave, funzionerà anche:

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

questa è una versione della risposta di Anurag Uniyal e qualcosa su cui stavo lavorando.

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'

La random.choicefunzione seleziona una voce casuale in un elenco. È inoltre possibile creare un elenco in modo da poter aggiungere il carattere fornell'istruzione. Alla fine str è ['t', 'm', '2', 'J', 'U', 'Q', '0', '4', 'C', 'K'], ma i str = "".join(str)take prenditi cura di quello, lasciandoti con 'tm2JUQ04CK'.

Spero che sia di aiuto!


Bello, ma avresti potuto usare range(num)invece, e str avrebbe potuto essere una stringa 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
Sebbene questo codice possa rispondere alla domanda, fornendo un contesto aggiuntivo riguardo al perché e / o al modo in cui risponde alla domanda migliorerebbe significativamente il suo valore a lungo termine. Si prega di modificare la risposta di aggiungere qualche spiegazione.
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="")

Qui la lunghezza della stringa può essere cambiata in for loop, ovvero per i in range (1, lunghezza) È un algoritmo semplice che è facile da capire. usa la lista in modo da poter scartare i caratteri che non ti servono.


1

Semplice:

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

Vorrei suggerirti la prossima opzione:

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

Modalità paranoica:

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

0

Due metodi:

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


Prova delle prestazioni :

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

Produzione :

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

Le prestazioni del primo metodo sono migliori.


0

Ho cercato quasi tutte le risposte, ma nessuna sembra più facile. Vorrei suggerire di provare la libreria passgen che viene generalmente utilizzata per creare password casuali.

Puoi generare stringhe casuali a tua scelta di lunghezza, punteggiatura, cifre, lettere e maiuscole.

Ecco il codice per il tuo caso:

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

0

Genera ID casuale a 16 byte contenente lettere, cifre, "_" e "-"

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


0

Stavo guardando le diverse risposte e mi sono preso il tempo per leggere la documentazione dei segreti

Il modulo segreti è usato per generare numeri casuali crittograficamente adatti per la gestione di dati come password, autenticazione account, token di sicurezza e segreti correlati.

In particolare, i segreti dovrebbero essere usati preferibilmente al generatore di numeri pseudo-casuali predefinito nel modulo casuale, progettato per modellare e simulare, non per sicurezza o crittografia.

Guardando di più su ciò che ha da offrire, ho trovato una funzione molto utile se vuoi imitare un ID come gli ID di Google Drive:

secrets.token_urlsafe ([nbytes = None])
Restituisce una stringa di testo casuale sicura per URL, contenente nbytes byte casuali. Il testo è codificato Base64, quindi in media ogni byte risulta in circa 1,3 caratteri . Se nbytes è Nessuno o non fornito, viene utilizzato un valore predefinito ragionevole.

Usalo nel modo seguente:

import secrets
import math

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

print(id_generator())

Emette un ID di lunghezza di 32 caratteri:

joXR8dYbBDAHpVs5ci6iD-oIgPhkeQFk

So che questo è leggermente diverso dalla domanda del PO, ma mi aspetto che sarebbe ancora utile per molti che stavano cercando lo stesso caso d'uso che stavo cercando.


-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

Ho trovato questo più semplice e pulito.

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 cambiare il 64 per variare la lunghezza, variare il CharacterPool per eseguire solo caratteri alfanumerici o solo numerici o caratteri strani o qualunque cosa tu voglia.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.