Zufällige Zeichenfolgengenerierung mit Großbuchstaben und Ziffern

1336

Ich möchte eine Zeichenfolge der Größe N generieren.

Es sollte aus Zahlen und englischen Großbuchstaben bestehen, wie z.

  • 6U1S75
  • 4Z4UKK
  • U911K4

Wie kann ich dies auf pythonische Weise erreichen?

Hellnar
quelle
11
Dies ist eine sehr beliebte Frage. Ich wünschte, ein Experte würde seine Einschätzung der Eindeutigkeit dieser Zufallszahlen für die Top-3-Antworten hinzufügen, dh die Kollisionswahrscheinlichkeit für den Bereich der Zeichenfolgengröße, beispielsweise von 6 bis 16.
Benutzer
8
@buffer Es ist einfach, die Anzahl der möglichen Kombinationen zu berechnen. 10 Zahlen + 26 Buchstaben = 36 mögliche Zeichen, hoch 6 (Länge der Zeichenfolge) entspricht ungefähr zwei Milliarden. Meine Faustregel für zufällige Werte lautet: "Wenn ich Werte für jeden Menschen auf der Erde generieren würde, wie viele Werte könnten sie jeweils haben?". In diesem Fall wäre das weniger als ein Wert pro Person. Wenn also Benutzer oder Objekte identifiziert werden sollen, sind es zu wenige Zeichen. Eine Alternative wäre, Kleinbuchstaben hinzuzufügen, wodurch Sie bei 62 ^ 6 = fast 57 Milliarden eindeutigen Werten landen.
Blixt
1
Und während es vielleicht albern erscheint, an die Weltbevölkerung zu denken, liegt das nur daran, dass Sie einen riesigen Puffer für mögliche Kollisionen wollen. Siehe das Geburtstagsproblem: en.wikipedia.org/wiki/Birthday_problem
Blixt
1
@buffer, Diese Antwort würde dich dann interessieren .
Anish Ramaswamy
Sollte dies nicht in "Kryptografisch sichere zufällige Zeichenfolgengenerierung ..." umbenannt werden ?
smci

Antworten:

2541

Antwort in einer Zeile:

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

oder noch kürzer ab Python 3.6 mit random.choices():

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

Eine kryptografisch sicherere Version; Siehe https://stackoverflow.com/a/23728630/2213647 :

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

Im Detail mit einer sauberen Funktion zur weiteren Wiederverwendung:

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

Wie funktioniert es ?

Wir importieren stringein Modul, das Sequenzen gemeinsamer ASCII-Zeichen enthält, und randomein Modul, das sich mit der Zufallsgenerierung befasst.

string.ascii_uppercase + string.digits Verkettet nur die Liste der Zeichen, die ASCII-Zeichen und -Ziffern in Großbuchstaben darstellen:

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

Dann verwenden wir ein Listenverständnis, um eine Liste von 'n' Elementen zu erstellen:

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

Im obigen Beispiel wird [die Liste verwendet, jedoch nicht in der id_generatorFunktion, sodass Python die Liste nicht im Speicher erstellt, sondern die Elemente im laufenden Betrieb einzeln generiert (mehr dazu hier ).

Anstatt zu fragen, elemob 'n' mal die Zeichenfolge erstellt werden soll , bitten wir Python, 'n' mal ein zufälliges Zeichen zu erstellen, das aus einer Folge von Zeichen ausgewählt wird:

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

Daher wird random.choice(chars) for _ in range(size)wirklich eine Folge von sizeZeichen erstellt. Charaktere, die zufällig ausgewählt werden aus 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']

Dann verbinden wir sie einfach mit einer leeren Zeichenfolge, sodass die Sequenz zu einer Zeichenfolge wird:

>>> ''.join(['a', 'b', 'b'])
'abb'
>>> [random.choice('abcde') for _ in range(3)]
['d', 'c', 'b']
>>> ''.join(random.choice('abcde') for _ in range(3))
'dac'
Ignacio Vazquez-Abrams
quelle
7
@jorelli: Es ist kein Listenverständnis; Es ist ein Generatorausdruck.
Ignacio Vazquez-Abrams
2
@joreilli: Ich habe in der Antwort einen kurzen Hinweis dazu und einen Link zu einer detaillierteren Antwort zu Iterable, Listenverständnis, Generatoren und schließlich dem Yield-Schlüsselwort hinzugefügt.
E-Satis
1
Ich würde ersetzen rangemit xrange.
Dr. Jan-Philip Gehrcke
1
Sehr hilfreich. Interessanterweise verwendet Django diesen Code zum Generieren von Passwörtern und CSRF-Token. Obwohl sollten Sie ersetzen randommit random.SystemRandom(): github.com/django/django/blob/...
Benutzer
1
@ Chiel92 random.sampleerstellt ersatzlose Samples, dh ohne die Möglichkeit, Zeichen zu wiederholen, was nicht den Anforderungen des OP entspricht. Ich denke nicht, dass dies für die meisten Anwendungen wünschenswert wäre.
Ontologe
557

Diese Stack Overflow-Frage ist das aktuelle Top-Google-Ergebnis für "Random String Python". Die aktuelle Top-Antwort lautet:

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

Dies ist eine ausgezeichnete Methode, aber das zufällige PRNG ist nicht kryptografisch sicher. Ich gehe davon aus, dass viele Leute, die diese Frage untersuchen, zufällige Zeichenfolgen für die Verschlüsselung oder Passwörter generieren möchten. Sie können dies sicher tun, indem Sie den obigen Code geringfügig ändern:

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

Verwenden random.SystemRandom()von / dev / urandom anstelle von nur zufälligen Verwendungen auf * nix-Computern und CryptGenRandom()in Windows. Dies sind kryptografisch sichere PRNGs. Die Verwendung random.choiceanstelle random.SystemRandom().choiceeiner Anwendung, die ein sicheres PRNG erfordert, kann möglicherweise verheerend sein. Angesichts der Beliebtheit dieser Frage wette ich, dass der Fehler bereits viele Male gemacht wurde.

Wenn Sie python3.6 oder höher verwenden, können Sie die neuen verwenden Geheimnisse Modul wie in erwähnt MSeifert Antwort :

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

In den Moduldokumenten werden auch praktische Möglichkeiten zum Generieren sicherer Token und Best Practices erläutert .

Randy Marsh
quelle
3
Ja, die offizielle Standardbibliothek für randomhat dies gewarnt: " Warnung : Die Pseudozufallsgeneratoren dieses Moduls sollten nicht aus Sicherheitsgründen verwendet werden. Verwenden Sie os.urandom () oder SystemRandom, wenn Sie einen kryptografisch sicheren Pseudozufallszahlengenerator benötigen. "" Hier ist die Referenz : random.SystemRandom und os.urandom
lord63. j
4
Gute Antwort. Kleiner Hinweis: Sie haben ihn geändert, string.uppercasewas je nach festgelegtem Gebietsschema zu unerwarteten Ergebnissen führen kann. Die Verwendung string.ascii_uppercase(oder string.ascii_letters + string.digitsfür base62 anstelle von base36) ist in Fällen, in denen die Codierung erforderlich ist, sicherer.
Blixt
kleine Anmerkung - besser zu nutzen , xrangeanstatt rangewie diese erzeugt eine In-Memory - Liste, während erstere einen Iterator erzeugt.
Guyarad
2
Wird der zufällige Stich immer einzigartig sein? Ich wollte einen Primärschlüssel verwenden.
Shakthydoss
3
@shakthydoss: nein. Möglicherweise wird "AAA000" zurückgegeben, bei dem es sich um eine zufällige Zeichenfolge handelt, und als nächstes "AAA000", bei dem es sich ebenfalls um eine zufällige Zeichenfolge handelt. Sie müssen explizit eine Prüfung auf Eindeutigkeit hinzufügen.
usr2564301
189

Verwenden Sie einfach die in Python integrierte UUID:

Wenn UUIDs für Ihre Zwecke in Ordnung sind, verwenden Sie das integrierte UUID- Paket.

Einzeilige Lösung:

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

In der Tiefenversion:

Beispiel:

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

Wenn Sie genau Ihr Format benötigen (z. B. "6U1S75"), können Sie dies folgendermaßen tun:

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
Bijan
quelle
14
+1 Für das Denken hinter der Frage. Vielleicht könnten Sie kurz den Unterschied zwischen uuid1 und uuid4 erklären.
Thomas Ahle
1
Wenn ich dreimal hintereinander uuid1 mache, erhalte ich: d161fd16-ab0f-11e3-9314-00259073e4a8, d3535b56-ab0f-11e3-9314-00259073e4a8, d413be32-ab0f-11e3-9314-00259073e4a8, die alle verdächtig erscheinen ( Die ersten 8 Zeichen unterscheiden sich und der Rest ist der gleiche. Dies ist nicht der Fall mit uuid4
Chase Roberts
9
uui1: Generieren Sie eine UUID aus einer Host-ID, einer Sequenznummer und der aktuellen Uhrzeit. uuid4: Generiere eine zufällige UUID.
Bijan
7
Wenn Sie das Casting von Zeichenfolgen und das Ersetzen von Bindestrichen überspringen möchten, können Sie einfach my_uuid.get_hex () oder uuid.uuid4 () aufrufen. Get_hex () und es wird eine Zeichenfolge zurückgegeben, die aus der uuid generiert wurde, die keine Bindestriche enthält.
dshap
8
Ist es eine gute Idee, eine UUID abzuschneiden? Je nachdem, wie klein es string_lengthist, kann die Wahrscheinlichkeit einer Kollision ein Problem sein.
Benutzer
44

Eine einfachere, schnellere, aber etwas weniger zufällige Methode ist die Verwendung, random.sampleanstatt jeden Buchstaben einzeln auszuwählen. Wenn n-Wiederholungen zulässig sind, vergrößern Sie Ihre zufällige Basis um das n-fache, z

import random
import string

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

Hinweis: random.sample verhindert die Wiederverwendung von Zeichen. Das Multiplizieren der Größe des Zeichensatzes ermöglicht mehrere Wiederholungen, aber sie sind immer noch weniger wahrscheinlich als eine rein zufällige Auswahl. Wenn wir uns für eine Zeichenfolge mit der Länge 6 entscheiden und 'X' als erstes Zeichen auswählen, sind im Auswahlbeispiel die Chancen, 'X' für das zweite Zeichen zu erhalten, die gleichen wie die Chancen, 'X' als das zu erhalten erstes Zeichen. In der random.sample-Implementierung beträgt die Wahrscheinlichkeit, 'X' als nachfolgendes Zeichen zu erhalten, nur 6/7 der Wahrscheinlichkeit, es als erstes Zeichen zu erhalten

Anurag Uniyal
quelle
8
Dieser Weg ist nicht schlecht, aber nicht ganz so zufällig wie die Auswahl jedes einzelnen Zeichens, da bei sampleIhnen niemals derselbe Charakter zweimal aufgelistet wird. Auch wird es natürlich für Nhöher als scheitern 36.
Bobince
Für den gegebenen Anwendungsfall (wenn keine Wiederholung in Ordnung ist) werde ich sagen, dass es immer noch die beste Lösung ist.
Anurag Uniyal
3
Eines der Beispiele hat eine Wiederholung, daher bezweifle ich, dass er Wiederholungen verbieten möchte.
Mark Byers
5
Wenn random.sample verhindert Charakter Wiederverwendung, macht die Größe des Zeichensatzes multipliziert mehrere Wiederholungen möglich , aber sie sind immer noch weniger wahrscheinlich dann in einer reinen Zufall Wahl , die sie sind. Wenn wir uns für eine Zeichenfolge mit der Länge 6 entscheiden und 'X' als erstes Zeichen auswählen, sind im Auswahlbeispiel die Chancen, 'X' für das zweite Zeichen zu erhalten, die gleichen wie die Chancen, 'X' als das zu erhalten erstes Zeichen. In der Implementierung von random.sample beträgt die Wahrscheinlichkeit, 'X' als nachfolgendes Zeichen zu erhalten, nur 5/6 der Wahrscheinlichkeit, es als erstes Zeichen zu erhalten.
pcurry
1
Die Wahrscheinlichkeit, dass ein bestimmtes Zeichen wiederholt wird, nimmt ab, wenn Sie sich durch die generierte Zeichenfolge bewegen. Wenn aus den 26 Großbuchstaben plus 10 Ziffern eine Zeichenfolge mit 6 Zeichen generiert wird und jedes Zeichen zufällig ausgewählt wird, tritt eine bestimmte Zeichenfolge mit der Häufigkeit 1 / (36 ^ 6) auf. Die Chance, 'FU3WYE' und 'XXXXXX' zu generieren, ist gleich. In der Beispielimplementierung beträgt die Chance, 'XXXXXX' zu generieren, (1 / (36 ^ 6)) * ((6/6) * (5/6) * (4/6) * (3/6) * (2 / 6) * (1/6)) aufgrund der nicht ersetzbaren Funktion von random.sample. 'XXXXXX' ist in der Beispielimplementierung 324-mal weniger wahrscheinlich.
pcurry
32
import uuid
lowercase_str = uuid.uuid4().hex  

lowercase_str ist ein zufälliger Wert wie 'cea8b32e00934aaea8c005a35d85a5c0'

uppercase_str = lowercase_str.upper()

uppercase_str ist 'CEA8B32E00934AAEA8C005A35D85A5C0'

Savad KP
quelle
2
uppercase_str[:N+1]
Yajo
@ Yajo Ja, wir können das Schneiden einschränken
Savad KP
2
@ Yajo: Nein, du willst den Hex-Wert nicht in Scheiben schneiden. Sie entfernen die Entropie im Vergleich zu einer vollständigen Folge von Großbuchstaben und Ziffern. Vielleicht codiert base32 stattdessen den Wert (leicht reduzierte Entropie von 36 ** n auf 32 ** n, immer noch besser als 16 ** n).
Martijn Pieters
19

Eine schnellere, einfachere und flexiblere Möglichkeit, dies zu tun, ist die Verwendung des strgenModuls ( pip install StringGenerator).

Generieren Sie eine 6-stellige Zufallszeichenfolge mit Großbuchstaben und Ziffern:

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

Erhalten Sie eine eindeutige Liste:

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

Garantieren Sie ein "Sonderzeichen" in der Zeichenfolge:

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

Eine zufällige HTML-Farbe:

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

usw.

Wir müssen uns bewusst sein, dass dies:

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

Möglicherweise ist keine Ziffer (oder kein Großbuchstabe) enthalten.

strgenist in der Entwicklerzeit schneller als jede der oben genannten Lösungen. Die Lösung von Ignacio bietet die schnellste Laufzeit und ist die richtige Antwort mit der Python-Standardbibliothek. Aber Sie werden es in dieser Form kaum jemals benutzen. Sie möchten SystemRandom (oder Fallback, falls nicht verfügbar) verwenden, sicherstellen, dass die erforderlichen Zeichensätze dargestellt werden, Unicode verwenden (oder nicht), sicherstellen, dass aufeinanderfolgende Aufrufe eine eindeutige Zeichenfolge erzeugen, eine Teilmenge einer der Zeichenklassen des Zeichenfolgenmoduls verwenden. usw. Dies alles erfordert viel mehr Code als in den bereitgestellten Antworten. Die verschiedenen Versuche, eine Lösung zu verallgemeinern, weisen alle Einschränkungen auf, die strgen mit einer einfachen Vorlagensprache mit größerer Kürze und Ausdruckskraft löst.

Es ist auf PyPI:

pip install StringGenerator

Offenlegung: Ich bin der Autor des strgen-Moduls.

Paul Wolf
quelle
12

Ab Python 3.6 sollten Sie das secretsModul verwenden, wenn es anstelle des randomModuls kryptografisch sicher sein soll (ansonsten ist diese Antwort identisch mit der von @Ignacio Vazquez-Abrams):

from secrets import choice
import string

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

Ein zusätzlicher Hinweis: Ein Listenverständnis ist bei str.joinVerwendung eines Generatorausdrucks schneller !

MSeifert
quelle
9

Wenn Sie eine zufällige Zeichenfolge anstelle einer pseudozufälligen benötigen , sollten Sie diese os.urandomals Quelle verwenden

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))
John La Rooy
quelle
3
Wie ist os.urandomnicht pseudozufällig? Es könnte einen besseren Algorithmus verwenden, um Zahlen zu generieren, die zufälliger sind, aber es ist immer noch pseudozufällig.
Tyilo
@ Tyilo, ich bin mir des Unterschieds zwischen /dev/randomund bewusst /dev/urandom. Das Problem ist, dass /dev/randomblockiert, wenn nicht genügend Entropie vorhanden ist, was die Nützlichkeit einschränkt. Zum einen ist ein einmaliges Pad /dev/urandom nicht gut genug, aber ich denke, es ist hier besser als Pseudozufällig.
John La Rooy
1
Ich würde sagen, dass beide /dev/randomund /dev/urandompseudozufällig sind, aber es könnte von Ihrer Definition abhängen.
Tyilo
9

Ich dachte, noch hätte niemand darauf geantwortet lol! Aber hey, hier ist mein eigener Versuch:

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))], "")
nemesisfixx
quelle
4
Ich werde das nicht ablehnen, aber ich denke, es ist viel zu kompliziert für eine so einfache Aufgabe. Der Rückausdruck ist ein Monster. Einfach ist besser als komplex.
Carl Smith
12
@CarlSmith, stimmt, meine Lösung scheint für die Aufgabe etwas übertrieben zu sein, aber ich war mir der anderen einfacheren Lösungen bewusst und wollte nur einen alternativen Weg zu einer guten Antwort finden. Ohne Freiheit ist Kreativität in Gefahr, also habe ich sie veröffentlicht.
Nemesisfixx
7

Diese Methode ist etwas schneller und etwas ärgerlicher als die von Ignacio veröffentlichte random.choice () -Methode.

Es nutzt die Natur von Pseudozufallsalgorithmen und setzt darauf, dass bitweise und Verschiebung schneller sind als das Generieren einer neuen Zufallszahl für jedes Zeichen.

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

... einen Generator erstellen, der jeweils 5-Bit-Zahlen 0..31 herausnimmt, bis keine mehr übrig sind

... verbinden () die Ergebnisse des Generators mit einer Zufallszahl mit den richtigen Bits

Bei Timeit war das Timing für Zeichenfolgen mit 32 Zeichen:

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

... aber bei 64 Zeichenketten verlieren Randbits;)

Ich würde diesen Ansatz wahrscheinlich nie im Produktionscode verwenden, wenn ich meine Mitarbeiter nicht wirklich mochte.

edit: aktualisiert, um der Frage zu entsprechen (nur Großbuchstaben und Ziffern), und verwende bitweise Operatoren & und >> anstelle von% und //

rauben
quelle
5

Ich würde es so machen:

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

Oder nur:

def rand_string(length, char_set=legals):

    return ''.join( random.choice(char_set) for _ in range(length) )
Carl Smith
quelle
5

Verwenden Sie die Funktion random.choice () von 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))

Die Dokumentation finden Sie hier http://docs.scipy.org/doc/numpy-1.10.0/reference/generated/numpy.random.choice.html

Mudit Jain
quelle
1
Warum sollte ich numpy random anstelle von python stdlib random verwenden?
Pax0r
Weil es mehr Optionen in Argumenten wie Länge, variable Wahrscheinlichkeit und Auswahl mit Ersetzung erlaubt.
Mudit Jain
5

Manchmal können 0 (Null) & O (Buchstabe O) verwirrend sein. Also benutze ich

import uuid
uuid.uuid4().hex[:6].upper().replace('0','X').replace('O','Y')
Aseem
quelle
4
>>> import string 
>>> import random

Die folgende Logik generiert immer noch eine Zufallsstichprobe mit 6 Zeichen

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

Keine Notwendigkeit, mit 6 zu multiplizieren

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

TK82HK
user128956
quelle
3
Diese Variante erzwingt jedoch, dass alle Zeichen unterschiedlich sind. Und es wird nicht funktionieren, wenn N größer als len ist (string.ascii_uppercase + string.digits)
MarSoft
3

Für diejenigen unter Ihnen, die funktionale Python mögen:

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

Es generiert einen unbestimmten [unendlichen] Iterator aus verbundenen zufälligen Sequenzen, indem es zuerst eine unbestimmte Sequenz zufällig ausgewählter Symbole aus dem Spendenpool generiert und diese Sequenz dann in Längenteile aufteilt, die dann verbunden werden. Es sollte mit jeder Sequenz funktionieren, die getitem unterstützt Standardmäßig wird einfach eine zufällige Folge von alphanumerischen Buchstaben generiert, die Sie jedoch leicht ändern können, um andere Dinge zu generieren:

Zum Beispiel, um zufällige Ziffern-Tupel zu generieren:

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

Wenn Sie next nicht für die Generierung verwenden möchten, können Sie es einfach aufrufbar machen:

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

Wenn Sie die Sequenz im laufenden Betrieb generieren möchten, setzen Sie einfach join auf identity.

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

Wie andere bereits erwähnt haben, stellen Sie die entsprechende Auswahlfunktion ein, wenn Sie mehr Sicherheit benötigen:

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

Die Standardauswahl ist choice, dass das gleiche Symbol für jeden Block mehrmals ausgewählt werden kann. Wenn Sie stattdessen möchten, dass dasselbe Mitglied höchstens einmal für jeden Block ausgewählt wird, gibt es eine mögliche Verwendung:

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

Wir verwenden sampleals unseren Selektor, um die vollständige Auswahl zu treffen, sodass die Chunks tatsächlich die Länge 1 haben, und um zu verbinden, rufen wir einfach auf, nextwelcher den nächsten vollständig generierten Chunk abruft, vorausgesetzt, dieses Beispiel scheint etwas umständlich und es ist ...

Samy Vilar
quelle
3

(1) Dies gibt Ihnen alle Großbuchstaben und Zahlen:

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) Wenn Sie später Kleinbuchstaben in Ihren Schlüssel aufnehmen möchten, funktioniert dies auch:

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  
Jacob
quelle
3

Dies ist eine Interpretation von Anurag Uniyals Antwort und etwas, an dem ich selbst gearbeitet habe.

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()
Stopit Donk
quelle
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'

Die random.choiceFunktion wählt einen zufälligen Eintrag in einer Liste aus. Sie erstellen auch eine Liste, damit Sie das Zeichen in die forAnweisung einfügen können . Am Ende ist str ['t', 'm', '2', 'J', 'U', 'Q', '0', '4', 'C', 'K'], aber die str = "".join(str)Takes kümmere dich darum und lasse dich bei 'tm2JUQ04CK'.

Hoffe das hilft!

AJ Uppal
quelle
Schön, aber Sie hätten range(num)stattdessen verwenden können, und str hätte eine Zeichenfolge sein können 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
Natascha
quelle
2
Obwohl dieser Code die Frage möglicherweise beantwortet, würde die Bereitstellung eines zusätzlichen Kontexts darüber, warum und / oder wie er die Frage beantwortet, ihren langfristigen Wert erheblich verbessern. Bitte bearbeiten Sie Ihre Antwort, um eine Erklärung hinzuzufügen.
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="")

Hier kann die Länge des Strings für die Schleife geändert werden, dh für i im Bereich (1, Länge). Es ist ein einfacher Algorithmus, der leicht zu verstehen ist. Es verwendet eine Liste, damit Sie nicht benötigte Zeichen verwerfen können.

lawlie8
quelle
1

Ein einfaches:

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
Hackaholic
quelle
0

Ich möchte Ihnen die nächste Option vorschlagen:

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

Paranoischer Modus:

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

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

Ausgabe :

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

Die Leistung der ersten Methode ist besser.

Bi Ao
quelle
0

Ich habe fast alle Antworten durchgesehen, aber keine davon sieht einfacher aus. Ich würde Ihnen empfehlen, die Passgen- Bibliothek auszuprobieren, mit der im Allgemeinen zufällige Passwörter erstellt werden.

Sie können zufällige Zeichenfolgen Ihrer Wahl aus Länge, Interpunktion, Ziffern, Buchstaben und Groß- / Kleinschreibung generieren .

Hier ist der Code für Ihren Fall:

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

Generieren Sie eine zufällige 16-Byte-ID mit Buchstaben, Ziffern, '_' und '-'

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

Steckdosenpaar
quelle
0

Ich sah mir die verschiedenen Antworten an und nahm mir Zeit, um die Dokumentation der Geheimnisse zu lesen

Das Geheimmodul wird zum Generieren kryptografisch starker Zufallszahlen verwendet, die zum Verwalten von Daten wie Kennwörtern, Kontoauthentifizierung, Sicherheitstoken und verwandten Geheimnissen geeignet sind.

Insbesondere sollten Geheimnisse dem Standard-Pseudozufallszahlengenerator im Zufallsmodul vorgezogen werden, der für die Modellierung und Simulation ausgelegt ist, nicht für Sicherheit oder Kryptographie.

Wenn ich mir genauer anschaue, was es zu bieten hat, habe ich eine sehr praktische Funktion gefunden, wenn Sie eine ID wie Google Drive IDs nachahmen möchten:

secret.token_urlsafe ([nbytes = None]) Gibt
eine zufällige URL-sichere Textzeichenfolge zurück, die nbytes zufällige Bytes enthält. Der Text ist Base64-codiert, sodass durchschnittlich jedes Byte ungefähr 1,3 Zeichen ergibt . Wenn nbytes None oder nicht angegeben ist, wird ein angemessener Standard verwendet.

Verwenden Sie es folgendermaßen:

import secrets
import math

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

print(id_generator())

Geben Sie eine ID mit einer Länge von 32 Zeichen aus:

joXR8dYbBDAHpVs5ci6iD-oIgPhkeQFk

Ich weiß, dass dies etwas anders ist als die Frage des OP, aber ich gehe davon aus, dass es für viele, die nach dem gleichen Anwendungsfall suchten, den ich gesucht habe, immer noch hilfreich sein wird.

Antonin GAVREL
quelle
-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
CONvid19
quelle
-2

Ich fand das einfacher und sauberer.

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 

Ändern Sie einfach die 64, um die Länge zu variieren, und ändern Sie den CharacterPool, um nur Alpha-Zahlen oder nur Zahlen oder seltsame Zeichen oder was auch immer Sie wollen.

MT Head
quelle