Je veux générer une chaîne de taille N.
Il doit être composé de chiffres et de lettres majuscules anglaises telles que:
Comment puis-je y parvenir de manière Pythonic ?
Répondez en une ligne:
''.join(random.choice(string.ascii_uppercase + string.digits) for _ in range(N))
ou même plus court en commençant par 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 de nettoyage 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 string
, un module contenant des séquences de caractères ASCII communs, et random
, un module traitant de la génération aléatoire.
string.ascii_uppercase + string.digits
concatène simplement la liste des caractères représentant des majuscules ASCII caractères et chiffres:
>>> 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 fonction id_generator
afin que Python ne crée pas la liste en mémoire, mais génère le éléments à la volée, un par un (plus à ce sujet ici ).
Au lieu de demander à créer 'n' fois la chaîne elem
, nous demanderons à Python de créer 'n' fois un caractère aléatoire, sélectionné à partir d'une séquence de caractères:
>>> random.choice("abcde")
'a'
>>> random.choice("abcde")
'd'
>>> random.choice("abcde")
'b'
Par conséquent, random.choice(chars) for _ in range(size)
crée réellement une séquence de size
caractères. Caractères choisis au hasard dans 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 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'
Cette question relative au dépassement de capacité en pile correspond au résultat actuel le plus récent dans Google pour "chaîne aléatoire Python". La principale 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 en mode aléatoire n'est pas sécurisé sur le plan cryptographique. Je suppose que beaucoup de personnes qui recherchent 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 apportant une petite modification au code ci-dessus:
''.join(random.SystemRandom().choice(string.ascii_uppercase + string.digits) for _ in range(N))
Utiliser random.SystemRandom()
au lieu de simplement aléatoire utilise/dev/urandom sur des machines * nix et CryptGenRandom()
sous Windows. Ce sont des PRNG sécurisés de manière cryptographique. Utiliser random.choice
au lieu de random.SystemRandom().choice
dans une application nécessitant un fichier sécurisé PRNG pourrait être dévastateur. Compte tenu de la popularité de cette question, je parie que de nombreuses erreurs ont déjà été commises. .
Si vous utilisez python3.6 ou une version ultérieure, vous pouvez utiliser le nouveau module secrets mentionné dans réponse de MSeifert :
''.join(secrets.choice(string.ascii_uppercase + string.digits) for _ in range(N))
La documentation du module décrit également des méthodes pratiques pour générer des jetons sécurisés et meilleures pratiques .
Si les UUID conviennent à vos besoins, utilisez le package id intégré.
import uuid; uuid.uuid4().hex.upper()[0:6]
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
Une méthode plus simple, plus rapide mais légèrement moins aléatoire consiste à utiliser random.sample
au 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. Multiplier la taille du jeu de caractères permet plusieurs répétitions, mais elles sont moins probables que dans un choix purement aléatoire. Si nous choisissons une chaîne de longueur 6 et que nous choisissons le premier caractère "X", dans l'exemple de choix, les chances d'obtenir le "X" pour le deuxième caractère sont les mêmes que les chances d'obtenir le "X". premier caractère. Dans l'implémentation random.sample, les chances d'obtenir "X" comme tout caractère ultérieur sont seulement 6/7 chances de l'obtenir comme premier caractère.
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'
En prenant la réponse de Ignacio, cela fonctionne avec Python 2.6:
import random
import string
N=6
print ''.join(random.choice(string.ascii_uppercase + string.digits) for _ in range(N))
Exemple de sortie:
JQUBT2
Une méthode plus rapide, plus simple et plus flexible consiste à utiliser le module strgen
(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']
Garantie 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))
pourrait ne pas contenir un chiffre (ou un caractère majuscule).
strgen
est plus rapide en temps développeur que n'importe laquelle des solutions ci-dessus. La solution d’Ignacio est la plus rapide en termes d’exécution et constitue la bonne réponse en utilisant la bibliothèque standard Python. Mais vous ne l'utiliserez presque jamais sous cette forme. Vous voudrez utiliser SystemRandom (ou fallback si non disponible), assurez-vous que les jeux de caractères requis sont représentés, utilisez unicode (ou non), assurez-vous que les appels successifs 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 différentes tentatives pour généraliser une solution ont toutes des limitations que strgen résout avec plus de brièveté et un pouvoir d’expression plus simple en utilisant un langage de template simple.
C'est sur PyPI:
pip install StringGenerator
Divulgation: Je suis l'auteur du module strgen.
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.
À partir de Python 3.6, vous devez utiliser le module secrets
si vous souhaitez qu'il soit cryptographiquement sûr à la place du random
module (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 de str.join
que d'utiliser une expression génératrice!
Je pensais que personne n'avait encore répondu à cela lol! Mais bon, voici le mien:
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))], "")
Si vous avez besoin d'une chaîne aléatoire plutôt que d'une pseudo-aléatoire , vous devez utiliser os.urandom
comme 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))
_
Cette méthode est légèrement plus rapide et légèrement plus agaçante que la méthode random.choice () publiée par Ignacio.
Il tire parti de la nature des algorithmes pseudo-aléatoires. Il est plus rapide que de générer 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ée un générateur qui prend 5 nombres de bits à la fois 0..31 jusqu'à ce qu'il n'en reste plus
... rejoindre () 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, randbits perd;)
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 en fonction de la question (majuscules et chiffres uniquement), et utilise les opérateurs au niveau des bits & et >> au lieu de% et //
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) )
Utilisez la fonction random.choice () de Numpy
import numpy as np
import string
if __== '__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
>>> 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
(1) Cela vous donnera toutes les majuscules et numéros:
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 ultérieurement 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
c’est une interprétation de la réponse d’Anurag Uniyal et une chose sur laquelle je travaillais 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()
Pour ceux 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 [infini] indéfini, de séquences aléatoires jointes, en générant d’abord une séquence indéfinie de symbole sélectionné de manière aléatoire dans le pool donneur, puis divise cette séquence en parties de longueur qui sont ensuite jointes. Elle doit fonctionner avec toute séquence prenant en charge getitem. , par défaut, il génère simplement une séquence aléatoire de lettres alphanumériques, bien que vous puissiez facilement le 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 for generation, 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 voulez générer la séquence à la volée, définissez simplement join à 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 choice
qui peut sélectionner le même symbole plusieurs fois pour chaque bloc, si vous préférez que le même membre soit sélectionné au plus une fois pour chaque bloc, 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 sample
comme sélecteur pour faire la sélection complète. Les morceaux ont donc une longueur de 1; pour nous rejoindre, nous appelons simplement next
qui récupère le prochain bloc entièrement généré, à supposer que cet exemple semble un peu encombrant et c'est ...
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 dans la boucle i.e pour i dans la plage (1, longueur). C'est un algorithme simple, facile à comprendre. il utilise la liste afin que vous puissiez supprimer les caractères dont vous n’avez pas besoin.
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
>>> 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 fonction random.choice
sélectionne une entrée aléatoire dans une liste. Vous créez également une liste pour pouvoir ajouter le caractère dans l'instruction for
. À la fin, str est ['t', 'm', '2', 'J', 'U', 'Q', '0', '4', 'C', 'K'], mais le str = "".join(str)
s'en charge, vous laissant avec 'tm2JUQ04CK'
.
J'espère que cela t'aides!
Parfois 0 (zéro) & O (lettre O) peuvent être déroutants. Donc j'utilise
import uuid
uuid.uuid4().hex[:6].upper().replace('0','X').replace('O','Y')
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
J'ai consulté presque toutes les réponses, mais aucune ne semble plus facile. Je vous suggère d'essayer la bibliothèque passgen 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 , de ponctuation, de chiffres, de lettres et de .
Voici le code pour votre cas:
from passgen import passgen
string_length = int(input())
random_string = passgen(length=string_length, punctuation=False, digits=True, letters=True, case='upper')
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))
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)))
Sortie:
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
La performance de la première méthode est meilleure.
Je voudrais vous suggérer la prochaine option:
import crypt
n = 10
crypt.crypt("any sring").replace('/', '').replace('.', '').upper()[-n:-1]
Mode paranoïque:
import uuid
import crypt
n = 10
crypt.crypt(str(uuid.uuid4())).replace('/', '').replace('.', '').upper()[-n:-1]
pour python 3 chaîne d'importation, aléatoire
'' .join (random.choice (string.ascii_lowercase + string.ascii_uppercase + string.digits) pour _ dans la plage (15))