Génération aléatoire de chaînes avec des lettres majuscules et des chiffres

1338

Je veux générer une chaîne de taille N.

Il doit être composé de chiffres et de lettres anglaises majuscules telles que:

  • 6U1S75
  • 4Z4UKK
  • U911K4

Comment puis-je y parvenir de manière pythonique ?

Hellnar
la source
11
C'est une question très populaire. Je souhaite qu'un expert ajoute son point de vue sur l'unicité de ces nombres aléatoires pour les 3 meilleures réponses, c'est-à-dire la probabilité de collision pour la plage de taille de chaîne, disons de 6 à 16.
utilisateur
8
@buffer Il est facile de calculer le nombre de combinaisons possibles. 10 chiffres + 26 lettres = 36 caractères possibles, à la puissance de 6 (longueur de chaîne) soit environ deux milliards. Ma règle de base pour les valeurs aléatoires est "si j'ai généré des valeurs pour chaque humain sur Terre, combien de valeurs pourraient-ils avoir chacune?". Dans ce cas, ce serait moins d'une valeur par personne, donc si c'est pour identifier des utilisateurs ou des objets, c'est trop peu de caractères. Une alternative serait d'ajouter des lettres minuscules, ce qui vous donne 62 ^ 6 = près de 57 milliards de valeurs uniques.
Blixt
1
Et même s'il peut sembler idiot de penser à la population mondiale, c'est simplement parce que vous voulez un énorme tampon pour les collisions potentielles. Voir le problème d'anniversaire: en.wikipedia.org/wiki/Birthday_problem
Blixt
1
@buffer, vous seriez alors intéressé par cette réponse .
Anish Ramaswamy
Ne devrait-il pas être renommé "Génération aléatoire de chaînes sécurisées cryptographiquement ..." ?
smci

Réponses:

2544

Répondez en une ligne:

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

ou encore plus court à partir de Python 3.6 en utilisant random.choices():

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

Une version cryptographiquement plus sécurisée; voir https://stackoverflow.com/a/23728630/2213647 :

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

En détail, avec une fonction propre pour une réutilisation ultérieure:

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

Comment ça marche ?

Nous importons stringun module qui contient des séquences de caractères ASCII communs et randomun module qui traite de la génération aléatoire.

string.ascii_uppercase + string.digits concatène simplement la liste des caractères représentant les caractères et chiffres ASCII majuscules:

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

Ensuite, nous utilisons une compréhension de liste pour créer une liste d'éléments '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']

Dans l'exemple ci-dessus, nous utilisons [pour créer la liste, mais nous ne le faisons pas dans la id_generatorfonction, donc Python ne crée pas la liste en mémoire, mais génère les éléments à la volée, un par un (plus à ce sujet ici ).

Au lieu de demander de créer 'n' fois la chaîne elem , nous demanderons à Python de créer 'n' fois un caractère aléatoire, choisi parmi une séquence de caractères:

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

C'est donc random.choice(chars) for _ in range(size)vraiment créer une séquence de sizepersonnages. Personnages choisis au hasard parmi 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']

Ensuite, nous les rejoignons simplement avec une chaîne vide afin que la séquence devienne une chaîne:

>>> ''.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
la source
7
@jorelli: Ce n'est pas une compréhension de liste; c'est une expression génératrice.
Ignacio Vazquez-Abrams
2
@joreilli: J'ai ajouté une note rapide à ce sujet dans la réponse, et un lien vers une réponse plus détaillée sur l'itérable, la compréhension de la liste, les générateurs et finalement le mot-clé yield.
e-satis
1
Je remplacerais rangepar xrange.
Dr.Jan-Philip Gehrcke
1
Très utile. Fait intéressant, Django utilise ce morceau de code pour générer des mots de passe et des jetons CSRF. Bien que vous devez remplacer randompar random.SystemRandom(): github.com/django/django/blob/…
utilisateur
1
@ Chiel92, random.samplecrée des échantillons sans remplacement, en d'autres termes, sans possibilité de répéter les caractères, ce qui n'est pas dans les exigences de l'OP. Je ne pense pas que ce serait souhaitable pour la plupart des applications.
ontologue
557

Cette question de débordement de pile est le meilleur résultat Google actuel pour "chaîne aléatoire Python". La meilleure réponse actuelle est:

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

C'est une excellente méthode, mais le PRNG aléatoire n'est pas sécurisé cryptographiquement. Je suppose que de nombreuses personnes recherchant cette question voudront générer des chaînes aléatoires pour le cryptage ou les mots de passe. Vous pouvez le faire en toute sécurité en effectuant une petite modification dans le code ci-dessus:

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

Utiliser random.SystemRandom()au lieu de simplement utiliser au hasard / dev / urandom sur les machines * nix et CryptGenRandom()sous Windows. Ce sont des PRNG cryptographiquement sécurisés. Utiliser random.choiceau lieu de random.SystemRandom().choicedans une application qui nécessite un PRNG sécurisé pourrait être potentiellement dévastateur, et étant donné la popularité de cette question, je parie que cette erreur a déjà été commise plusieurs fois.

Si vous utilisez python3.6 ou supérieur, vous pouvez utiliser le nouveau module secrets comme mentionné dans la réponse de MSeifert :

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

Les documents du module discutent également des moyens pratiques de générer des jetons sécurisés et des meilleures pratiques .

Randy Marsh
la source
3
Oui, la bibliothèque standard officielle pour randoma averti ceci: " Avertissement : Les générateurs pseudo-aléatoires de ce module ne doivent pas être utilisés à des fins de sécurité. Utilisez os.urandom () ou SystemRandom si vous avez besoin d'un générateur de nombres pseudo-aléatoires cryptographiquement sécurisé. " Voici la référence: random.SystemRandom et os.urandom
lord63. j
4
Très bonne réponse. Petite note: vous l'avez modifié, ce string.uppercasequi peut entraîner des résultats inattendus en fonction de la configuration locale. L'utilisation string.ascii_uppercase(ou string.ascii_letters + string.digitspour base62 au lieu de base36) est plus sûre dans les cas où l'encodage est impliqué.
Blixt
petite note - préférable d'utiliser xrangeau lieu de rangecar ce dernier génère une liste en mémoire, tandis que le premier crée un itérateur.
guyarad le
2
la piqûre aléatoire sera-t-elle toujours unique? je voulais utiliser une clé primaire.
shakthydoss
3
@shakthydoss: non. Il peut retourner "AAA000", qui est une chaîne aléatoire, et ensuite "AAA000", qui est également une chaîne aléatoire. Vous devez explicitement ajouter une vérification d'unicité.
usr2564301
189

Utilisez simplement l'uuid intégré de Python:

Si les UUID conviennent à vos besoins, utilisez le package uuid intégré.

Solution en une ligne:

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

Version détaillée:

Exemple:

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

Si vous avez besoin exactement de votre format (par exemple, "6U1S75"), vous pouvez le faire comme ceci:

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
la source
14
+1 Pour avoir réfléchi à la question. Peut-être pourriez-vous expliquer brièvement la différence entre uuid1 et uuid4.
Thomas Ahle
1
Si je fais uuid1 trois fois de suite, j'obtiens: d161fd16-ab0f-11e3-9314-00259073e4a8, d3535b56-ab0f-11e3-9314-00259073e4a8, d413be32-ab0f-11e3-9314-00259073e4a8, qui semblent tous similaires (suspects) les 8 premiers caractères diffèrent et les autres sont les mêmes). Ce n'est pas le cas avec uuid4
Chase Roberts
9
uui1: générer un UUID à partir d'un ID d'hôte, d'un numéro de séquence et de l'heure actuelle. uuid4: générer un UUID aléatoire.
Bijan
7
Si vous souhaitez ignorer le transtypage de chaîne et le remplacement du trait d'union, vous pouvez simplement appeler my_uuid.get_hex () ou uuid.uuid4 (). Get_hex () et il renverra une chaîne générée à partir de l'uuid qui n'a pas de tirets.
dshap
8
Est-ce une bonne idée de tronquer un UUID? Selon sa taille string_length, la probabilité de collision peut être préoccupante.
utilisateur
44

Une manière plus simple, plus rapide mais légèrement moins aléatoire consiste à utiliser random.sampleau lieu de choisir chaque lettre séparément. Si n répétitions sont autorisées, agrandissez votre base aléatoire de n fois, par exemple

import random
import string

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

Remarque: random.sample empêche la réutilisation des caractères, la multiplication de la taille du jeu de caractères rend plusieurs répétitions possibles, mais elles sont encore moins probables qu'elles sont dans un pur choix aléatoire. Si nous optons pour une chaîne de longueur 6 et que nous choisissons «X» comme premier caractère, dans l'exemple de choix, les chances d'obtenir «X» pour le deuxième caractère sont les mêmes que les chances d'obtenir «X» comme premier caractère. Dans l'implémentation random.sample, les chances d'obtenir «X» comme n'importe quel caractère suivant sont seulement 6/7 la chance de l'obtenir comme premier caractère

Anurag Uniyal
la source
8
De cette façon, ce n'est pas mauvais, mais ce n'est pas aussi aléatoire que de sélectionner chaque personnage séparément, car samplevous n'obtiendrez jamais le même personnage deux fois. Bien sûr, cela échouera Nplus que 36.
bobince
pour le cas d'utilisation donné (si aucune répétition n'est correcte), je dirai que c'est toujours la meilleure solution.
Anurag Uniyal
3
L'un des exemples a une répétition, donc je doute qu'il cherche à interdire les répétitions.
Mark Byers
5
Si random.sample empêche la réutilisation des caractères, la multiplication de la taille du jeu de caractères rend plusieurs répétitions possibles , mais elles sont encore moins probables qu'elles sont dans un pur choix aléatoire. Si nous optons pour une chaîne de longueur 6 et que nous choisissons «X» comme premier caractère, dans l'exemple de choix, les chances d'obtenir «X» pour le deuxième caractère sont les mêmes que les chances d'obtenir «X» comme premier caractère. Dans l'implémentation random.sample, les chances d'obtenir «X» comme n'importe quel caractère suivant n'ont que 5/6 de chances de l'obtenir comme premier caractère.
pcurry
1
La possibilité de faire répéter un caractère particulier diminue lorsque vous vous déplacez dans la chaîne générée. En générant une chaîne de 6 caractères à partir des 26 lettres majuscules plus 10 chiffres, en choisissant au hasard chaque caractère indépendamment, toute chaîne particulière se produit avec la fréquence 1 / (36 ^ 6). Les chances de générer «FU3WYE» et «XXXXXX» sont les mêmes. Dans l'exemple d'implémentation, la chance de générer 'XXXXXX' est (1 / (36 ^ 6)) * ((6/6) * (5/6) * (4/6) * (3/6) * (2 / 6) * (1/6)) en raison de la fonction de non-remplacement de random.sample. «XXXXXX» est 324 fois moins probable dans l'exemple de mise en œuvre.
pcurry
32
import uuid
lowercase_str = uuid.uuid4().hex  

lowercase_str est une valeur aléatoire comme 'cea8b32e00934aaea8c005a35d85a5c0'

uppercase_str = lowercase_str.upper()

uppercase_str est 'CEA8B32E00934AAEA8C005A35D85A5C0'

Savad KP
la source
2
uppercase_str[:N+1]
Yajo
@Yajo oui, nous pouvons limiter l'utilisation de la découpe
Savad KP
2
@Yajo: non, vous ne voulez pas couper la valeur hexadécimale. Vous supprimez l'entropie par rapport à une séquence complète de lettres majuscules et de chiffres. Peut-être que coder en base32 la valeur à la place (entropie légèrement réduite, de 36 ** n à 32 ** n, toujours mieux que 16 ** n).
Martijn Pieters
19

Un moyen plus rapide, plus facile et plus flexible de le faire est d'utiliser le strgenmodule ( pip install StringGenerator).

Générez une chaîne aléatoire de 6 caractères avec des lettres majuscules et des chiffres:

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

Obtenez une liste unique:

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

Garantissez un caractère "spécial" dans la chaîne:

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

Une couleur HTML aléatoire:

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

etc.

Nous devons être conscients que ceci:

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

peut ne pas contenir de chiffre (ou de caractère majuscule).

strgenest plus rapide en temps de développement que n'importe laquelle des solutions ci-dessus. La solution d'Ignacio est l'exécution la plus rapide et constitue la bonne réponse en utilisant la bibliothèque standard Python. Mais vous ne l'utiliserez presque jamais sous cette forme. Vous souhaiterez utiliser SystemRandom (ou un repli s'il n'est pas disponible), assurez-vous que les jeux de caractères requis sont représentés, utilisez unicode (ou non), assurez-vous que les invocations successives produisent une chaîne unique, utilisez un sous-ensemble de l'une des classes de caractères du module de chaîne, etc. Tout cela nécessite beaucoup plus de code que dans les réponses fournies. Les diverses tentatives de généralisation d'une solution ont toutes des limites que strgen résout avec une plus grande brièveté et une puissance expressive en utilisant un langage de modèle simple.

C'est sur PyPI:

pip install StringGenerator

Divulgation: je suis l'auteur du module strgen.

Paul Wolf
la source
12

À partir de Python 3.6, vous devez utiliser le secretsmodule si vous avez besoin qu'il soit sécurisé cryptographiquement au lieu du randommodule (sinon cette réponse est identique à celle de @Ignacio Vazquez-Abrams):

from secrets import choice
import string

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

Une remarque supplémentaire: une compréhension de liste est plus rapide dans le cas str.joinque l'utilisation d'une expression de générateur!

MSeifert
la source
10

Basé sur une autre réponse Stack Overflow, le moyen le plus léger de créer une chaîne aléatoire et un nombre hexadécimal aléatoire , une meilleure version que la réponse acceptée serait:

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

Plus vite.

Gubbi
la source
1
C'est bien, mais il n'utilisera que «AF» et non «A-Z». De plus, le code devient un peu moins agréable lors du paramétrage N.
Thomas Ahle
9

Si vous avez besoin d'une chaîne aléatoire plutôt que pseudo aléatoire , vous devez utiliser os.urandomcomme source

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
la source
3
Comment n'est os.urandompas pseudo aléatoire? Il pourrait utiliser un meilleur algorithme pour générer des nombres plus aléatoires, mais il est toujours pseudo aléatoire.
Tyilo
@Tyilo, je suis conscient de la différence entre /dev/randomet /dev/urandom. Le problème est que les /dev/randomblocs quand il n'y a pas assez d'entropie ce qui limite son utilité. Pour un pad unique, ce /dev/urandom n'est pas suffisant, mais je pense que c'est mieux que pseudo aléatoire ici.
John La Rooy
1
Je dirais que les deux /dev/randomet /dev/urandomest pseudo aléatoire, mais cela pourrait dépendre de votre définition.
Tyilo
9

Je pensais que personne n'avait encore répondu à ça lol! Mais bon, voici mon propre essai:

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
la source
4
Je ne voterai pas contre, mais je pense que c'est beaucoup trop compliqué pour une tâche aussi simple. L'expression de retour est un monstre. Simple, c'est mieux que complexe.
Carl Smith,
12
@CarlSmith, vrai ma solution semble un peu exagérée pour la tâche, mais j'étais au courant des autres solutions plus simples, et je voulais juste trouver un itinéraire alternatif vers une bonne réponse. Sans liberté, la créativité est en danger, donc je suis allé de l'avant et je l'ai affichée.
nemesisfixx
7

Cette méthode est légèrement plus rapide et légèrement plus ennuyeuse que la méthode random.choice () publiée par Ignacio.

Il tire parti de la nature des algorithmes pseudo-aléatoires et mise sur les bits et les décalages plus rapidement que la génération d'un nouveau nombre aléatoire pour chaque caractère.

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

... créer un générateur qui supprime les nombres de 5 bits à la fois 0..31 jusqu'à ce qu'il n'en reste plus

... join () les résultats du générateur sur un nombre aléatoire avec les bons bits

Avec Timeit, pour les chaînes de 32 caractères, le timing était le suivant:

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

... mais pour 64 chaînes de caractères, les randbits perdent;)

Je n'utiliserais probablement jamais cette approche dans le code de production à moins que je n'aime vraiment pas mes collègues.

edit: mis à jour pour répondre à la question (majuscule et chiffres uniquement), et utilisez les opérateurs au niveau du bit & et >> au lieu de% et //

Rob
la source
5

Je le ferais de cette façon:

import random
from string import digits, ascii_uppercase

legals = digits + ascii_uppercase

def rand_string(length, char_set=legals):

    output = ''
    for _ in range(length): output += random.choice(char_set)
    return output

Ou juste:

def rand_string(length, char_set=legals):

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

Utilisez la fonction random.choice () de Numpy

import numpy as np
import string        

if __name__ == '__main__':
    length = 16
    a = np.random.choice(list(string.ascii_uppercase + string.digits), length)                
    print(''.join(a))

La documentation est ici http://docs.scipy.org/doc/numpy-1.10.0/reference/generated/numpy.random.choice.html

Mudit Jain
la source
1
Pourquoi devrais-je utiliser numpy random au lieu de python stdlib random?
Pax0r
Parce qu'il permet plus d'options dans les arguments comme la longueur, la probabilité variable et la sélection avec remplacement.
Mudit Jain
5

Parfois, 0 (zéro) et O (lettre O) peuvent prêter à confusion. J'utilise donc

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

la logique suivante génère toujours un échantillon aléatoire de 6 caractères

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

Pas besoin de multiplier par 6

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

TK82HK
user128956
la source
3
Mais cette variante obligera tous les personnages à être différents. Et cela ne fonctionnera pas si N est plus grand que len (string.ascii_uppercase + string.digits)
MarSoft
3

Pour ceux d'entre vous qui aiment le python fonctionnel:

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

Il génère un itérateur indéfini [infini], de séquences aléatoires jointes, en générant d'abord une séquence indéfinie de symboles sélectionnés au hasard à partir du pool de donneurs, puis en divisant cette séquence en parties de longueur qui sont ensuite jointes, elle devrait fonctionner avec n'importe quelle séquence qui prend en charge getitem , par défaut, il génère simplement une séquence aléatoire de lettres alphanumériques, mais vous pouvez facilement modifier pour générer d'autres choses:

par exemple pour générer des tuples aléatoires de chiffres:

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

si vous ne voulez pas utiliser next pour la génération, vous pouvez simplement le rendre appelable:

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

si vous souhaitez générer la séquence à la volée, définissez simplement join sur identité.

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

Comme d'autres l'ont mentionné, si vous avez besoin de plus de sécurité, définissez la fonction de sélection appropriée:

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

le sélecteur par défaut est celui choicequi peut sélectionner le même symbole plusieurs fois pour chaque bloc, si au contraire vous souhaitez que le même membre soit sélectionné au plus une fois pour chaque bloc, alors, une utilisation possible:

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

nous utilisons samplecomme notre sélecteur, pour faire la sélection complète, donc les morceaux sont en fait de longueur 1, et pour rejoindre nous appelons simplement nextqui récupère le prochain morceau complètement généré, étant donné que cet exemple semble un peu lourd et qu'il est ...

Samy Vilar
la source
3

(1) Cela vous donnera tous les chiffres et majuscules:

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) Si vous souhaitez plus tard inclure des lettres minuscules dans votre clé, cela fonctionnera également:

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
la source
3

c'est une prise sur la réponse d'Anurag Uniyal et quelque chose que je travaillais sur moi-même.

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
la source
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.choicefonction sélectionne une entrée aléatoire dans une liste. Vous créez également une liste afin de pouvoir ajouter le caractère dans l' forinstruction. À la fin, str est ['t', 'm', '2', 'J', 'U', 'Q', '0', '4', 'C', 'K'], mais les str = "".join(str)prises prendre soin de cela, vous laissant avec 'tm2JUQ04CK'.

J'espère que cela t'aides!

AJ Uppal
la source
Bien, mais vous auriez pu utiliser à la range(num)place, et str aurait pu être une chaîne 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
Natasha
la source
2
Bien que ce code puisse répondre à la question, fournir un contexte supplémentaire concernant pourquoi et / ou comment il répond à la question améliorerait considérablement sa valeur à long terme. Veuillez modifier votre réponse pour ajouter des explications.
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="")

Ici, la longueur de la chaîne peut être modifiée pour la boucle, c'est-à-dire pour i dans la plage (1, longueur). C'est un algorithme simple qui est facile à comprendre. il utilise la liste afin que vous puissiez éliminer les caractères dont vous n'avez pas besoin.

lawlie8
la source
1

Un simple:

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
la source
0

Je voudrais vous suggérer la prochaine option:

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

Mode paranoïaque:

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

Deux méthodes:

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


Référence :

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

Production :

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

Les performances de la première méthode sont meilleures.

Bi Ao
la source
0

J'ai parcouru presque toutes les réponses, mais aucune ne semble plus facile. Je vous suggère d'essayer le passgen bibliothèque qui est généralement utilisée pour créer des mots de passe aléatoires.

Vous pouvez générer des chaînes aléatoires de votre choix de longueur, ponctuation, chiffres, lettres et casse.

Voici le code de votre cas:

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

Générer un ID aléatoire de 16 octets contenant des lettres, des chiffres, «_» et «-»

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

socketpair
la source
0

Je regardais les différentes réponses et pris le temps de lire la documentation des secrets

Le module secrets est utilisé pour générer des nombres aléatoires cryptographiquement solides adaptés à la gestion de données telles que les mots de passe, l'authentification de compte, les jetons de sécurité et les secrets associés.

En particulier, les secrets doivent être utilisés de préférence au générateur de nombres pseudo-aléatoires par défaut dans le module aléatoire, qui est conçu pour la modélisation et la simulation, pas pour la sécurité ou la cryptographie.

En examinant davantage ce qu'il a à offrir, j'ai trouvé une fonction très pratique si vous souhaitez imiter un identifiant comme les identifiants Google Drive:

secrets.token_urlsafe ([nbytes = None])
Renvoie une chaîne de texte sécurisée pour les URL, contenant nbytes octets aléatoires. Le texte est encodé en Base64, donc en moyenne chaque octet donne environ 1,3 caractère . Si nbytes est None ou non fourni, une valeur par défaut raisonnable est utilisée.

Utilisez-le de la manière suivante:

import secrets
import math

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

print(id_generator())

Afficher un identifiant de longueur de 32 caractères:

joXR8dYbBDAHpVs5ci6iD-oIgPhkeQFk

Je sais que cela est légèrement différent de la question du PO, mais je m'attends à ce que cela soit toujours utile à beaucoup de ceux qui recherchaient le même cas d'utilisation que je cherchais.

Antonin GAVREL
la source
-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
la source
-2

J'ai trouvé que c'était plus simple et plus propre.

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 

Modifiez simplement le 64 pour varier la longueur, faites varier le CharacterPool pour faire de l'alpha uniquement alphanumérique ou numérique uniquement ou des caractères étranges ou tout ce que vous voulez.

MT Head
la source