Willekeurige tekenreeksgeneratie met hoofdletters en cijfers

Ik wil een string van maat N genereren.

Het moet bestaan uit cijfers en Engelse hoofdletters, zoals:

  • 6U1S75
  • 4Z4UKK
  • U911K4

Hoe kan ik dit op een pythonischemanier bereiken?


Antwoord 1, autoriteit 100%

Antwoord in één regel:

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

of zelfs korter, beginnend met Python 3.6 met behulp van random.choices():

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

Een cryptografisch veiligere versie:zie dit bericht

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

In details, met een schone functie voor verder hergebruik:

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

Hoe werkt het?

We importeren string, een module die reeksen van veelvoorkomende ASCII-tekens bevat, en random, een module die zich bezighoudt met willekeurige generatie.

string.ascii_uppercase + string.digitsvoegt gewoon de lijst met tekens samen die ASCII-tekens en cijfers in hoofdletters vertegenwoordigen:

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

Vervolgens gebruiken we een lijstbegrip om een lijst met ‘n’-elementen te maken:

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

In het bovenstaande voorbeeld gebruiken we [om de lijst te maken, maar dat doen we niet in de functie id_generator, dus Python maakt de lijst niet in het geheugen, maar genereert de elementen on-the-fly, één voor één (meer hierover hier).

In plaats van te vragen om ‘n’ keer de tekenreeks elemte maken, vragen we Python om ‘n’ keer een willekeurig teken te maken, gekozen uit een reeks tekens:

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

Daarom creëert random.choice(chars) for _ in range(size)echt een reeks van sizetekens. Tekens die willekeurig worden gekozen uit 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']

Vervolgens voegen we ze gewoon samen met een lege string, zodat de reeks een string wordt:

>>> ''.join(['a', 'b', 'b'])
'abb'
>>> [random.choice('abcde') for _ in range(3)]
['d', 'c', 'b']
>>> ''.join(random.choice('abcde') for _ in range(3))
'dac'

Antwoord 2, autoriteit 21%

Deze Stack Overflow-vraag is het huidige topresultaat van Google voor ‘random string Python’. Het huidige topantwoord is:

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

Dit is een uitstekende methode, maar de willekeurige PRNGis cryptografisch niet veilig. Ik neem aan dat veel mensen die deze vraag onderzoeken, willekeurige strings voor codering of wachtwoorden willen genereren. U kunt dit veilig doen door een kleine wijziging aan te brengen in de bovenstaande code:

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

Gebruik random.SystemRandom()in plaats van willekeurig /dev/urandom op *nix-machines en CryptGenRandom()in Windows. Dit zijn cryptografisch beveiligde PRNG’s. Het gebruik van random.choicein plaats van random.SystemRandom().choicein een toepassing die een veilige PRNG vereist, kan potentieel verwoestend zijn, en gezien de populariteit van deze vraag, wed ik dat die fout is al vele malen gemaakt.

Als je python3.6 of hoger gebruikt, kun je de nieuwe geheimenmodule zoals vermeld in antwoord van MSeifert:

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

De moduledocumenten bespreken ook handige manieren om veilige tokens te genererenen best practices.


Antwoord 3, autoriteit 8%

Gebruik gewoon de ingebouwde uuid van Python:

Als UUID’s geschikt zijn voor uw doeleinden, gebruik dan de ingebouwde uuidpakket.

Eenregelige oplossing:

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

Uitgebreide versie:

Voorbeeld:

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

Als u precies uw indeling nodig heeft (bijvoorbeeld “6U1S75”), kunt u dit als volgt doen:

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

Antwoord 4, autoriteit 2%

Een eenvoudigere, snellere maar iets minder willekeurige manier is om random.samplete gebruiken in plaats van elke letter afzonderlijk te kiezen. Als n-herhalingen zijn toegestaan, vergroot u uw willekeurige basis met n keer, bijvoorbeeld

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

Opmerking:
random.sample voorkomt hergebruik van karakters, het vermenigvuldigen van de grootte van de karakterset maakt meerdere herhalingen mogelijk, maar ze zijn nog steeds minder waarschijnlijk dan bij een puur willekeurige keuze. Als we gaan voor een string van lengte 6, en we kiezen ‘X’ als het eerste teken, in het keuzevoorbeeld, is de kans om ‘X’ te krijgen voor het tweede teken hetzelfde als de kans om ‘X’ te krijgen als het eerste karakter. In de random.sample-implementatie is de kans om ‘X’ als een volgend teken te krijgen slechts 6/7 van de kans om het als het eerste teken te krijgen


Antwoord 5

import uuid
lowercase_str = uuid.uuid4().hex  

lowercase_stris een willekeurige waarde zoals 'cea8b32e00934aaea8c005a35d85a5c0'

uppercase_str = lowercase_str.upper()

uppercase_stris 'CEA8B32E00934AAEA8C005A35D85A5C0'


6

Vanaf Python 3.6 op u moet de Secrets Module gebruiken Als je het nodig hebt om cryptografisch veilig te zijn in plaats van de randommodule (anders is dit antwoord identiek aan die van @ignacio Vazquez-Abrams):

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

Eén extra noot: een lijst-begrip is sneller in het geval van str.joindan het gebruik van een expressie van generator!


7

Gebaseerd op een andere stapel & nbsp; overflow antwoord, meest lichtgewicht manier om een ​​willekeurige reeks te maken en een willekeurig hexadecimaal nummer , een betere versie dan het geaccepteerde antwoord zou zijn:

('%06x' % random.randrange(16**6)).upper()

veel sneller.


Antwoord 8

Ik dacht dat nog niemand hierop had gereageerd lol! Maar goed, hier doe ik het zelf:

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

Antwoord 9

Als je een willekeurige tekenreeks nodig hebt in plaats van een pseudo-willekeurige-tekenreeks, moet je os.urandomals de bron

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

Antwoord 10

Deze methode is iets sneller en iets vervelender dan de random.choice() methode die Ignacio heeft gepost.

Het maakt gebruik van de aard van pseudo-willekeurige algoritmen, en banken op bitsgewijze en en shift zijn sneller dan het genereren van een nieuw willekeurig getal voor elk teken.

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

…maak een generator die 5 bit-nummers per keer 0..31 eruit haalt totdat er geen meer over is

…join() de resultaten van de generator op een willekeurig getal met de juiste bits

Met Timeit, voor strings van 32 tekens, was de timing:

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

…maar voor reeksen van 64 tekens verliezen randbits 😉

Ik zou deze benadering waarschijnlijk nooit gebruiken in productiecode, tenzij ik mijn collega’s echt niet mocht.

bewerken: aangepast aan de vraag (alleen hoofdletters en cijfers), en gebruik bitsgewijze operatoren & en >> in plaats van % en //


Antwoord 11

Ik zou het zo doen:

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

Of gewoon:

def rand_string(length, char_set=legals):
    return ''.join( random.choice(char_set) for _ in range(length) )

Antwoord 12

Gebruik de functie random.choice() van 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))

Documentatie is hier http: //docs.cipy.org/doc/numpy-1.10.0/reference/generated/numpy.raandom.choice.html


13

soms 0 (nul) & amp; O (letter o) kan verwarrend zijn. Dus ik gebruik

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

14

>>> import string 
>>> import random

De volgende logica genereert nog steeds 6 tekens willekeurig monster

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

Niet nodig om te vermenigvuldigen met 6

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

15

Voor degenen onder u die van functioneel python genieten:

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

Het genereert onbepaalde [oneindig] repeater, of verbonden willekeurige sequenties, door het eerst opwekken onbepaalde opeenvolging van willekeurig geselecteerde symbool uit het geven pool, dan breken deze sequentie in lengte delen die vervolgens wordt verbonden, moet het werken met elke sequentie dat ondersteunt getItem, standaard is simpelweg genereert een willekeurige reeks alfanumerieke letters, hoewel je gemakkelijk kunt wijzigen om andere dingen te genereren:

bijvoorbeeld om willekeurige tupels cijfers te genereren:

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

als u niet wilt gaan voor de opwekking te gebruiken kun je gewoon maken het af te roepen:

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

Als u de volgorde op het eenvoudig te stellen fly te genereren mee te doen met identiteit.

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

Zoals anderen al hebben gezegd als u meer zekerheid dan stel de juiste select functie:

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

de standaardselector is choicedie hetzelfde symbool meerdere keren kan selecteren voor elke chunk, als u in plaats daarvan wilt dat hetzelfde lid maximaal één keer voor elke chunk wordt geselecteerd, dan is er één mogelijk gebruik:

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

we gebruiken sampleals onze selector, om de volledige selectie te doen, dus de chunks zijn eigenlijk lengte 1, en om mee te doen noemen we gewoon nextdie de volgende volledig ophaalt gegenereerde chunk, hoewel dit voorbeeld een beetje omslachtig lijkt en het is …


Antwoord 16

(1) Dit geeft je alle hoofdletters en cijfers:

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) Als u later kleine letters in uw sleutel wilt opnemen, dan werkt dit ook:

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  

Antwoord 17

dit is een kijk op de reactie van Anurag Uniyal en iets waar ik zelf mee bezig was.

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

Antwoord 18

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

Antwoord 19

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

Hier kan de lengte van de string worden gewijzigd in for-lus, d.w.z. voor i in range (1,length)
Het is een eenvoudig algoritme dat gemakkelijk te begrijpen is. het gebruikt een lijst, zodat u tekens kunt weggooien die u niet nodig hebt.


Antwoord 20

Ik keek naar de verschillende antwoorden en nam de tijd om de documentatie van geheimen

De geheimenmodule wordt gebruikt voor het genereren van cryptografisch sterke willekeurige getallen die geschikt zijn voor het beheren van gegevens zoals wachtwoorden, accountauthenticatie, beveiligingstokens en gerelateerde geheimen.

In het bijzonder moeten geheimen worden gebruikt in plaats van de standaard pseudo-willekeurige nummergenerator in de willekeurige module, die is ontworpen voor modellering en simulatie, geen beveiliging of cryptografie.

Kijk meer in wat het te bieden heeft, ik heb een zeer handige functie gevonden als je een ID als ID’s van Google Drive wilt mimiceren:

Secrets.token_urlSafe ([nbytes = geen])
Retourneer een willekeurige URL-veilige tekststring, die NBYTES willekeurige bytes bevat. De tekst is BASE64 gecodeerd, dus heeft gemiddeld elke byte in ongeveer 1,3 tekens . Als NBYTES geen of niet wordt geleverd, wordt een redelijke standaard gebruikt.

Gebruik het de volgende manier:

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

Uitgang A 32 Lengte-ID:

joXR8dYbBDAHpVs5ci6iD-oIgPhkeQFk

Ik weet dat dit enigszins afwijkt van de vraag van de OP, maar ik verwacht dat het nog steeds nuttig zou zijn voor velen die op zoek waren naar hetzelfde gebruik waar ik naar op zoek was.


21

Een eenvoudige:

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

22

Ik zou u volgende optie willen voorstellen:

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

Paranoic-modus:

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

23

Twee methoden:

import random, math

def randStr_1(chars:str, length:int) -> str:
    chars *= math.ceil(length / len(chars))
    chars = letters[0:length]
    chars = list(chars)
    random.shuffle(characters)
    return ''.join(chars)

def randStr_2(chars:str, length:int) -> str:
    return ''.join(random.choice(chars) for i in range(chars))

benchmark:

from timeit import timeit
setup = """
import os, subprocess, time, string, random, math
def randStr_1(letters:str, length:int) -> str:
    letters *= math.ceil(length / len(letters))
    letters = letters[0:length]
    letters = list(letters)
    random.shuffle(letters)
    return ''.join(letters)
def randStr_2(letters:str, length:int) -> str:
    return ''.join(random.choice(letters) for i in range(length))
"""
print('Method 1 vs Method 2', ', run 10 times each.')
for length in [100,1000,10000,50000,100000,500000,1000000]:
    print(length, 'characters:')
    eff1 = timeit("randStr_1(string.ascii_letters, {})".format(length), setup=setup, number=10)
    eff2 = timeit("randStr_2(string.ascii_letters, {})".format(length), setup=setup, number=10)
    print('\t{}s : {}s'.format(round(eff1, 6), round(eff2, 6)))
    print('\tratio = {} : {}\n'.format(eff1/eff1, round(eff2/eff1, 2)))

Uitvoer:

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

De prestaties van de eerste methode zijn beter.


Antwoord 24

Genereer een willekeurige 16-byte ID met letters, cijfers, ‘_’ en ‘-‘

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


Antwoord 25

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

Antwoord 26

Als u een eenvoudig te gebruiken maar zeer aanpasbare sleutelgenerator wilt gebruiken, gebruikt u key-generatorPYPI-pakket.

Hier is de GitHub Repo waar u de volledige documentatie kunt vinden.

U kunt het aanpassen om een ​​string jist te geven zoals u wilt met veel meer opties. Hier is een voorbeeld:

from key_generator.key_generator import generate
custom_key = generate(2, ['-', ':'], 3, 10, type_of_value = 'char', capital = 'mix', seed = 17).get_key()
print(custom_key)  # ZLFdHXIUe-ekwJCu

Ik hoop dat dit helpt 🙂

DISCLAIMER: Hiermee gebruikt u de key-generatorbibliotheek die ik heb gemaakt.


27

Geen van de antwoorden tot nu toe garanderen de aanwezigheid van bepaalde categorieën tekens zoals bovenste, lagere, cijfers enz.; Dus andere antwoorden kunnen resulteren in wachtwoorden die geen cijfers hebben, enz. Verrast dat een dergelijke functie geen deel uitmaakt van standaard Lib. Dit is wat ik gebruik:

def random_password(*, nchars = 7, min_nupper = 3, ndigits = 3, nspecial = 3, special=string.punctuation):
    letters = random.choices(string.ascii_lowercase, k=nchars)
    letters_upper = random.choices(string.ascii_uppercase, k=min_nupper)
    digits = random.choices(string.digits, k=ndigits)
    specials = random.choices(special, k=nspecial)
    password_chars = letters + letters_upper + digits + specials
    random.shuffle(password_chars)
    return ''.join(password_chars)

28

Ik heb deze methode gebruikt om willekeurige reeks lengte n van A – & GT te genereren; z

import random
s = ''.join(random.choice([chr(i) for i in range(ord('a'),ord('z'))]) for _ in range(10))

Other episodes