Wie erzeuge ich eine Zeichenfolge der Größe N aus Zahlen und englischen Großbuchstaben wie:
- 6U1S75
- 4Z4UKK
- U911K4
Hellnar
Wie erzeuge ich eine Zeichenfolge der Größe N aus Zahlen und englischen Großbuchstaben wie:
Randy Marsch
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 die PRNG in random ist nicht kryptografisch sicher. Ich nehme an, 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 eine kleine Änderung im obigen Code vornehmen:
''.join(random.SystemRandom().choice(string.ascii_uppercase + string.digits) for _ in range(N))
Verwenden random.SystemRandom()
statt nur zufällig verwendet /dev/urandom auf *nix-Rechnern und CryptGenRandom()
unter Windows. Dies sind kryptografisch sichere PRNGs. Verwenden random.choice
Anstatt von random.SystemRandom().choice
in einer Anwendung, die ein sicheres PRNG erfordert, könnte möglicherweise verheerend sein, und angesichts der Popularität dieser Frage wette ich, dass dieser Fehler bereits viele Male gemacht wurde.
Wenn Sie Python 3.6 oder höher verwenden, können Sie die neue verwenden Geheimnisse Modul wie in MSeiferts Antwort erwähnt:
''.join(secrets.choice(string.ascii_uppercase + string.digits) for _ in range(N))
Die Moduldokumentation erörtert auch bequeme Möglichkeiten, um sichere Token generieren und empfohlene Vorgehensweise.
Ja, die offizielle Standardbibliothek für random
hat dies gewarnt: “Warnung: Die Pseudozufallsgeneratoren dieses Moduls sollten nicht für Sicherheitszwecke 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
– Herr63. j
16. Mai 2015 um 14:30 Uhr
Gute Antwort. Kleine Anmerkung: Sie haben es geändert in string.uppercase
was je nach Gebietsschema zu unerwarteten Ergebnissen führen kann. Verwenden string.ascii_uppercase
(oder string.ascii_letters + string.digits
für base62 statt base36) ist sicherer, wenn es um Codierung geht.
– Blixt
17. Mai 2015 um 18:03 Uhr
kleine Anmerkung – besser zu verwenden xrange
Anstatt von range
da letzteres eine In-Memory-Liste generiert, während ersteres einen Iterator erstellt.
– Kerl
31. Juli 2016 um 11:44 Uhr
Wird der zufällige Stich immer einzigartig sein? Ich wollte einen Primärschlüssel verwenden.
– Shakthydoss
27. September 2016 um 8:45 Uhr
@shakthydoss: nein. Es kann “AAA000” zurückgeben, was eine zufällige Zeichenfolge ist, und als nächstes “AAA000”, was eine ist Auch eine zufällige Zeichenfolge. Sie müssen explizit eine Prüfung auf Eindeutigkeit hinzufügen.
– Jongware
2. März 2018 um 11:15 Uhr
+1 Für das Nachdenken hinter der Frage. Vielleicht könnten Sie kurz den Unterschied zwischen uuid1 und uuid4 erklären.
– Thomas Ahle
29. Januar 2014 um 12:36 Uhr
uui1: Generieren Sie eine UUID aus einer Host-ID, einer Sequenznummer und der aktuellen Uhrzeit. uuid4: Generiert eine zufällige UUID.
– Bijan
14. März 2014 um 5:19 Uhr
Wenn Sie das Casting und Ersetzen von Bindestrichen überspringen möchten, können Sie einfach my_uuid.get_hex() oder uuid.uuid4().get_hex() aufrufen und es wird eine aus der uuid generierte Zeichenfolge ohne Bindestriche zurückgegeben.
– dshap
11. April 2014 um 0:50 Uhr
Ist es eine gute Idee, eine UUID zu kürzen? Je nachdem wie klein string_length
Das heißt, die Wahrscheinlichkeit einer Kollision kann ein Problem sein.
– Benutzer
21. Juni 2014 um 7:01 Uhr
Warum sich darauf beschränken nur Hex-Zeichen. Base64 oder Base32 (nur für Großbuchstaben und 6 verschiedene Ziffern), um einen Zufallscode zu codieren os.urandom()
Bytes-Sequenz. Umgehen Sie die uuid
Zwischenhändler für mehr Geschwindigkeit!
– Martijn Pieters
♦
24. Januar 2018 um 13:39 Uhr
Anurag Uniyal
Eine einfachere, schnellere, aber etwas weniger zufällige Methode ist die Verwendung random.sample
Anstatt jeden Buchstaben einzeln auszuwählen, Wenn n-Wiederholungen erlaubt sind, vergrößern Sie Ihre Zufallsbasis 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, die Vervielfachung der Größe des Zeichensatzes macht mehrere Wiederholungen möglich, aber sie sind immer noch weniger wahrscheinlich als bei einer rein zufälligen Auswahl. Wenn wir uns für eine Zeichenfolge der Länge 6 entscheiden und „X“ als erstes Zeichen auswählen, sind die Chancen, „X“ für das zweite Zeichen zu erhalten, im Auswahlbeispiel die gleichen wie die Chancen, „X“ als das zu erhalten erstes Zeichen. In der random.sample-Implementierung beträgt die Chance, „X“ als nachfolgendes Zeichen zu erhalten, nur 6/7 der Chance, es als erstes Zeichen zu erhalten
Das ist nicht schlecht, aber nicht ganz so zufällig, wie wenn man jedes Zeichen separat auswählt, wie bei sample
Sie werden niemals denselben Charakter zweimal aufgelistet bekommen. Auch natürlich wird es scheitern N
höher als 36
.
– Bobin
13. Februar 2010 um 12:54 Uhr
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
13. Februar 2010 um 14:30 Uhr
Eines der Beispiele hat eine Wiederholung, also bezweifle ich, dass er versucht, Wiederholungen zu verbieten.
– Mark Byers
13. Februar 2010 um 14:34 Uhr
Wenn random.sample die Wiederverwendung von Zeichen verhindert, führt die Multiplikation der Größe des Zeichensatzes zu mehreren Wiederholungen möglichaber es sind noch weniger wahrscheinlich dann sind sie in einer rein zufälligen Auswahl. Wenn wir uns für eine Zeichenfolge der Länge 6 entscheiden und „X“ als erstes Zeichen auswählen, sind die Chancen, „X“ für das zweite Zeichen zu erhalten, im Auswahlbeispiel die gleichen wie die Chancen, „X“ als das zu erhalten erstes Zeichen. In der random.sample-Implementierung beträgt die Chance, „X“ als nachfolgendes Zeichen zu erhalten, nur 5/6 der Chance, es als erstes Zeichen zu erhalten.
– pcurry
31. August 2013 um 19:11 Uhr
Die Wahrscheinlichkeit, dass ein bestimmtes Zeichen wiederholt wird, sinkt, wenn Sie sich durch die generierte Zeichenfolge bewegen. Durch Generieren einer Zeichenfolge von 6 Zeichen aus den 26 Großbuchstaben plus 10 Ziffern, wobei jedes Zeichen zufällig unabhängig ausgewählt wird, tritt jede 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-Ersetzungsfunktion von random.sample. „XXXXXX“ ist in der Beispielimplementierung 324-mal weniger wahrscheinlich.
– pcurry
31. August 2013 um 19:24 Uhr
Jajo
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'
Das ist nicht schlecht, aber nicht ganz so zufällig, wie wenn man jedes Zeichen separat auswählt, wie bei sample
Sie werden niemals denselben Charakter zweimal aufgelistet bekommen. Auch natürlich wird es scheitern N
höher als 36
.
– Bobin
13. Februar 2010 um 12:54 Uhr
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
13. Februar 2010 um 14:30 Uhr
Eines der Beispiele hat eine Wiederholung, also bezweifle ich, dass er versucht, Wiederholungen zu verbieten.
– Mark Byers
13. Februar 2010 um 14:34 Uhr
Wenn random.sample die Wiederverwendung von Zeichen verhindert, führt die Multiplikation der Größe des Zeichensatzes zu mehreren Wiederholungen möglichaber es sind noch weniger wahrscheinlich dann sind sie in einer rein zufälligen Auswahl. Wenn wir uns für eine Zeichenfolge der Länge 6 entscheiden und „X“ als erstes Zeichen auswählen, sind die Chancen, „X“ für das zweite Zeichen zu erhalten, im Auswahlbeispiel die gleichen wie die Chancen, „X“ als das zu erhalten erstes Zeichen. In der random.sample-Implementierung beträgt die Chance, „X“ als nachfolgendes Zeichen zu erhalten, nur 5/6 der Chance, es als erstes Zeichen zu erhalten.
– pcurry
31. August 2013 um 19:11 Uhr
Die Wahrscheinlichkeit, dass ein bestimmtes Zeichen wiederholt wird, sinkt, wenn Sie sich durch die generierte Zeichenfolge bewegen. Durch Generieren einer Zeichenfolge von 6 Zeichen aus den 26 Großbuchstaben plus 10 Ziffern, wobei jedes Zeichen zufällig unabhängig ausgewählt wird, tritt jede 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-Ersetzungsfunktion von random.sample. „XXXXXX“ ist in der Beispielimplementierung 324-mal weniger wahrscheinlich.
– pcurry
31. August 2013 um 19:24 Uhr
Brutus
Ab Python 3.6 sollten Sie die verwenden Geheimnis-Modul wenn Sie kryptografisch sicher sein müssen anstelle von random
Modul (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)])
Eine zusätzliche Anmerkung: ein Listenverständnis ist schneller bei str.join
als einen Generatorausdruck zu verwenden!
Dies ist eine sehr beliebte Frage. Ich wünschte, ein Experte würde seine Meinung zur Eindeutigkeit dieser Zufallszahlen für die Top-3-Antworten hinzufügen, dh die Kollisionswahrscheinlichkeit für den Bereich der Zeichenfolgengröße, sagen wir von 6 bis 16.
– Benutzer
21. Juni 2014 um 7:06 Uhr
@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 etwa 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, was Sie bei 62 ^ 6 = fast 57 Milliarden eindeutigen Werten landet.
– Blixt
17. Mai 2015 um 18:17 Uhr
Und obwohl es albern erscheinen mag, an die Weltbevölkerung zu denken, liegt das nur daran, dass Sie einen riesigen Puffer für potenzielle Kollisionen haben möchten. Siehe das Geburtstagsproblem: en.wikipedia.org/wiki/Birthday_problem
– Blixt
17. Mai 2015 um 18:18 Uhr
@buffer, diese Antwort würde dich dann interessieren.
– Anish Ramaswamy
20. August 2015 um 2:09 Uhr
Sollte das nicht umbenannt werden “Kryptografisch sichere Generierung zufälliger Zeichenfolgen …”?
– smci
9. September 2018 um 1:09 Uhr