Я хочу створити рядок розміром N.
Він повинен складатися з цифр і великих англійських літер, таких як:
- 6U1S75
- 4Z4UKK
- U911K4
Як я можу досягти цього пітонічним способом?
Я хочу створити рядок розміром N.
Він повинен складатися з цифр і великих англійських літер, таких як:
Як я можу досягти цього пітонічним способом?
Відповіді:
Відповідь в одному рядку:
''.join(random.choice(string.ascii_uppercase + string.digits) for _ in range(N))
або навіть коротше, починаючи з Python 3.6, використовуючи random.choices()
:
''.join(random.choices(string.ascii_uppercase + string.digits, k=N))
Криптографічно більш безпечна версія; дивіться https://stackoverflow.com/a/23728630/2213647 :
''.join(random.SystemRandom().choice(string.ascii_uppercase + string.digits) for _ in range(N))
Детально, з чистою функцією для подальшого повторного використання:
>>> 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'
Як це працює ?
Ми імпортуємо string
, модуль, який містить послідовності загальних символів ASCII, і random
модуль, який має справу з випадковим генеруванням.
string.ascii_uppercase + string.digits
просто поєднує список символів, що представляють великі символи та цифри ASCII:
>>> string.ascii_uppercase
'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
>>> string.digits
'0123456789'
>>> string.ascii_uppercase + string.digits
'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'
Тоді ми використовуємо розуміння списку, щоб створити список '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']
У наведеному вище прикладі ми використовуємо [
для створення списку, але ми не виконуємо цю id_generator
функцію, тому Python не створює список у пам'яті, а генерує елементи по ходу (детальніше про це тут ).
Замість того, щоб просити створити рядок "n" разів elem
, ми попросимо Python створити "n" разів випадковий символ, вибраний із послідовності символів:
>>> random.choice("abcde")
'a'
>>> random.choice("abcde")
'd'
>>> random.choice("abcde")
'b'
Тому random.choice(chars) for _ in range(size)
справді створюється послідовність size
символів. Символи, вибрані випадковим чином 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']
Тоді ми просто з'єднуємо їх із порожнім рядком, щоб послідовність перетворилася на рядок:
>>> ''.join(['a', 'b', 'b'])
'abb'
>>> [random.choice('abcde') for _ in range(3)]
['d', 'c', 'b']
>>> ''.join(random.choice('abcde') for _ in range(3))
'dac'
range
на xrange
.
random
на random.SystemRandom()
: github.com/django/django/blob/…
random.sample
створює зразки без заміни, іншими словами, без можливості повторення символів, що не відповідає вимогам ОП. Я не думаю, що це було б бажано для більшості програм.
Це запитання про переповнення стека - це поточний найкращий результат Google для "випадкового рядка Python". Поточна відповідь:
''.join(random.choice(string.ascii_uppercase + string.digits) for _ in range(N))
Це відмінний метод, але PRNG випадково не є криптографічно захищеним. Я припускаю, що багато людей, які досліджують це питання, захочуть генерувати випадкові рядки для шифрування чи паролів. Ви можете це зробити безпечно, зробивши невелику зміну вищевказаного коду:
''.join(random.SystemRandom().choice(string.ascii_uppercase + string.digits) for _ in range(N))
Використання random.SystemRandom()
замість випадкових випадків використання / dev / urandom на * nix машинах та CryptGenRandom()
в Windows. Це криптографічно захищені PRNG. Використання random.choice
замість random.SystemRandom().choice
програми, яка вимагає захищеного PRNG, може бути потенційно руйнівною, і враховуючи популярність цього питання, я вважаю, що помилка була зроблена вже багато разів.
Якщо ви використовуєте python3.6 або вище, ви можете використовувати новий модуль секретів, як зазначено у відповіді MSeifert :
''.join(secrets.choice(string.ascii_uppercase + string.digits) for _ in range(N))
Документи модулів також обговорюють зручні способи генерування захищених маркерів та найкращі практики .
random
цього попереджає: " Попередження : Псевдовипадкові генератори цього модуля не повинні використовуватися з метою безпеки. Використовуйте os.urandom () або SystemRandom, якщо вам потрібен криптографічно захищений генератор псевдовипадкових чисел. " Ось посилання: random.SystemRandom та os.urandom
string.uppercase
що може призвести до несподіваних результатів залежно від набору локальних даних. Використання string.ascii_uppercase
(або string.ascii_letters + string.digits
для base62 замість base36) безпечніше у випадках, коли йдеться про кодування.
xrange
замість того, range
як останній генерує список пам'яті, тоді як перший створює ітератор.
Якщо UUID не відповідають вашим цілям, використовуйте вбудований пакет uuid .
import uuid; uuid.uuid4().hex.upper()[0:6]
Приклад:
import uuid
uuid.uuid4() #uuid4 => full random uuid
# Outputs something like: UUID('0172fc9a-1dac-4414-b88d-6b9a6feb91ea')
Якщо вам потрібен саме ваш формат (наприклад, "6U1S75"), ви можете зробити це так:
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
string_length
, ймовірність зіткнення може викликати стурбованість.
Більш простий, швидший, але трохи менш випадковий спосіб - використовувати random.sample
замість того, щоб вибирати кожну букву окремо, Якщо дозволено n-повторень, збільшити випадкову основу в n разів, наприклад
import random
import string
char_set = string.ascii_uppercase + string.digits
print ''.join(random.sample(char_set*6, 6))
Примітка: random.sample перешкоджає повторному використанню символів, примноження розміру набору символів робить можливими кілька повторень, але вони все ще менш ймовірні, тоді вони перебувають у чистому випадковому виборі. Якщо ми шукаємо рядок довжиною 6 і вибираємо "X" як перший символ, у прикладі вибору шанси отримати "X" для другого символу такі ж, як шанси отримати "X" як Перший персонаж. У реалізації random.sample шанси отримати "X" як будь-який наступний символ лише 6/7 шанс отримати його як першого символу
sample
ви ніколи не будете перераховувати одного і того ж символу двічі. Крім того, звичайно, вона вийде з ладу для N
вище 36
.
import uuid
lowercase_str = uuid.uuid4().hex
lowercase_str
- випадкове значення, як 'cea8b32e00934aaea8c005a35d85a5c0'
uppercase_str = lowercase_str.upper()
uppercase_str
є 'CEA8B32E00934AAEA8C005A35D85A5C0'
uppercase_str[:N+1]
Швидший, простіший і гнучкіший спосіб зробити це - використовувати strgen
модуль ( pip install StringGenerator
).
Створіть 6-символьний випадковий рядок із великих букв та цифр:
>>> from strgen import StringGenerator as SG
>>> SG("[\u\d]{6}").render()
u'YZI2CI'
Отримайте унікальний список:
>>> SG("[\l\d]{10}").render_list(5,unique=True)
[u'xqqtmi1pOk', u'zmkWdUr63O', u'PGaGcPHrX2', u'6RZiUbkk2i', u'j9eIeeWgEF']
Забезпечте один "спеціальний" символ у рядку:
>>> SG("[\l\d]{10}&[\p]").render()
u'jaYI0bcPG*0'
Довільний колір HTML:
>>> SG("#[\h]{6}").render()
u'#CEdFCa'
тощо.
Ми повинні мати на увазі, що це:
''.join(random.choice(string.ascii_uppercase + string.digits) for _ in range(N))
може не містити в ньому цифри (або великого символу).
strgen
є швидшим у часі розробника, ніж будь-яке з перерахованих вище рішень. Рішення від Ignacio - це найшвидший час виконання і є правильною відповіддю за допомогою стандартної бібліотеки Python. Але навряд чи ви будете використовувати його в такому вигляді. Ви хочете використовувати SystemRandom (або резервний запас, якщо його немає), переконайтеся, що потрібні набори символів представлені, використовуйте unicode (чи ні), переконайтеся, що послідовні виклики створюють унікальну рядок, використовуйте підмножину одного з класів символів рядкового модуля, і т. д. Для цього потрібно набагато більше коду, ніж у наданих відповідях. Всі різні спроби узагальнити рішення мають обмеження, які strgen вирішує з більшою стислістю та виразністю з використанням простої мови шаблонів.
Це на PyPI:
pip install StringGenerator
Розкриття інформації: я автор модуля strgen.
З Python 3.6 ви повинні використовувати secrets
модуль, якщо він вам потрібен для криптографічного захисту замість random
модуля (інакше ця відповідь ідентична відповіді @Ignacio Vazquez-Abrams):
from secrets import choice
import string
''.join([choice(string.ascii_uppercase + string.digits) for _ in range(N)])
Ще одна примітка: розуміння списку відбувається швидше, str.join
ніж використання генераторного виразу!
На основі іншої відповіді на переповнення стека, найлегшого способу створення випадкового рядка та випадкового шістнадцяткового числа , кращою версією, ніж прийнята відповідь, буде:
('%06x' % random.randrange(16**6)).upper()
набагато швидше.
N
.
Якщо вам потрібен випадковий рядок, а не псевдо випадковий , ви повинні використовувати os.urandom
як джерело
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))
os.urandom
псевдо випадково? Можливо, використовувати кращий алгоритм для генерування чисел, які є більш випадковими, але це все ще псевдовипадкові.
/dev/random
і /dev/urandom
. Проблема полягає в тому, що /dev/random
блокує, коли недостатньо ентропії, що обмежує її корисність. Для одного разу прокладка /dev/urandom
недостатньо хороша, але я думаю, що тут краще, ніж псевдо випадкові.
/dev/random
і інше /dev/urandom
є псевдо випадковим, але це може залежати від вашого визначення.
Я думав, ніхто ще не відповів на це, хай! Але ей, ось я іду на це:
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))], "")
Цей метод трохи швидший і трохи більше дратує, ніж метод random.choice (), розміщений Ігнасіо.
Він використовує природу псевдовипадкових алгоритмів, а банки на бітові та зсувні швидкості, ніж генерування нового випадкового числа для кожного символу.
# 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')
... створити генератор, який виймає 5 бітових чисел одночасно 0..31, поки нічого не залишиться
... приєднати () результати генератора на випадкове число з потрібними бітами
Для Timeit для 32-символьних рядків час був такий:
[('generate_with_random_choice', 28.92901611328125),
('generate_with_randbits', 20.0293550491333)]
... але для 64 символьних рядків randbits програє;)
Я, мабуть, ніколи не використовував би такий підхід у виробничому коді, якщо б справді не любив своїх колег.
редагувати: оновлено відповідно до запитання (лише великі і великі цифри), а також використовувати побітові оператори & і >> замість% та //
Я зробив би це так:
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
Або просто:
def rand_string(length, char_set=legals):
return ''.join( random.choice(char_set) for _ in range(length) )
Використовуйте функцію random.choice () 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))
Документація тут http://docs.scipy.org/doc/numpy-1.10.0/reference/generated/numpy.random.choice.html
>>> import string
>>> import random
наступна логіка все ще генерує випадкову вибірку з 6 символів
>>> print ''.join(random.sample((string.ascii_uppercase+string.digits),6))
JT7K3Q
Не потрібно множувати на 6
>>> print ''.join(random.sample((string.ascii_uppercase+string.digits)*6,6))
TK82HK
Для тих, хто любить функціональний пітон:
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))))
Він генерує невизначений [нескінченний] ітератор з об'єднаних випадкових послідовностей, спочатку генеруючи невизначену послідовність випадково вибраного символу з даючого пулу, потім розбиваючи цю послідовність на частини довжини, яка потім з'єднується, вона повинна працювати з будь-якою послідовністю, яка підтримує getitem , за замовчуванням він просто генерує випадкову послідовність алфавітних цифрових літер, хоча ви можете легко модифікувати для створення інших речей:
наприклад, для генерації випадкових кортезів цифр:
>>> 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)
якщо ви не хочете використовувати наступне для покоління, ви можете просто зробити його дзвінким:
>>> irand_tuples = irand_seqs(xrange(10), join=tuple)
>>> make_rand_tuples = partial(next, irand_tuples)
>>> make_rand_tuples()
(1, 6, 2, 8, 1, 9)
якщо ви хочете генерувати послідовність на льоту, просто встановіть приєднатись до ідентичності.
>>> irand_tuples = irand_seqs(xrange(10), join=identity)
>>> selections = next(irand_tuples)
>>> next(selections)
8
>>> list(selections)
[6, 3, 8, 2, 2]
Як уже згадували інші, якщо вам потрібен більший захист, тоді встановіть відповідну функцію вибору:
>>> from random import SystemRandom
>>> rand_strs = irand_seqs(select=SystemRandom().choice)
'QsaDxQ'
селектором за замовчуванням є той, choice
що може вибрати один і той же символ кілька разів для кожного фрагменту, якщо замість цього ви хочете, щоб той самий член був обраний максимум один раз для кожного фрагменту, тоді можливо одне можливе використання:
>>> 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]
ми використовуємо sample
як наш селектор, щоб зробити повний вибір, тому шматки насправді довжиною 1, а для приєднання ми просто називаємо, next
який отримує наступний повністю генерований фрагмент, наданий цей приклад здається трохи громіздким, і це ...
(1) Це дасть вам усі великі літери та цифри:
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) Якщо згодом ви хочете включити малі літери у свій ключ, це також спрацює:
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
це сприйняття відповіді Анурага Уніала і те, що я працював над собою.
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()
>>> 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'
random.choice
Функція вибирає випадкову запис в списку. Ви також створюєте список, щоб ви могли додати символу у for
виписці. В кінці вул знаходиться [ 'т', 'т', '2', 'J', 'U', 'Q', '0', '4', 'C', 'К'], але str = "".join(str)
приймає піклуйтеся про це, залишаючи вас'tm2JUQ04CK'
.
Сподіваюся, це допомагає!
range(num)
натомість, а str могла бути рядком str += random.choice(chars)
.
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
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="")
Тут можна змінити довжину рядка для циклу, тобто для i в діапазоні (1, довжина). Простий алгоритм, який легко зрозуміти. він використовує список, щоб ви могли відкинути символи, які вам не потрібні.
Простий:
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
Два способи:
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))
Орієнтир:
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)))
Вихід:
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
Виконання першого методу краще.
Я хотів майже всі відповіді, але жодна з них не виглядає легшою. Я б запропонував вам спробувати пасген бібліотеку яка зазвичай використовується для створення випадкових паролів.
Ви можете генерувати випадкові рядки на ваш вибір довжини, пунктуації, цифр, літер та .
Ось код вашої справи:
from passgen import passgen
string_length = int(input())
random_string = passgen(length=string_length, punctuation=False, digits=True, letters=True, case='upper')
Я переглядав різні відповіді і потребував часу, щоб прочитати документацію секретів
Модуль секретів використовується для генерування криптографічно сильних випадкових чисел, придатних для управління даними, такими як паролі, автентифікація облікового запису, маркери безпеки та пов’язані з ними секрети.
Зокрема, секрети слід використовувати в перевазі генератора псевдовипадкових чисел за замовчуванням у випадковому модулі, який призначений для моделювання та моделювання, а не для захисту чи криптографії.
Розглядаючи детальніше, що вона може запропонувати, я знайшов дуже зручну функцію, якщо ви хочете імітувати ідентифікатор, такий як ідентифікатори Google Drive:
secrets.token_urlsafe ([nbytes = None])
Повертає випадковий текстовий рядок, безпечний для URL-адрес, що містить випадкові байти nbytes. Текст кодується Base64, тому в середньому кожен байт має приблизно 1,3 символу . Якщо нбайт не вказаний або не надається, використовується розумний замовчування.
Використовуйте його наступним чином:
import secrets
import math
def id_generator():
id = secrets.token_urlsafe(math.floor(32 / 1.3))
return id
print(id_generator())
Виведіть ідентифікатор довжини 32 символів:
joXR8dYbBDAHpVs5ci6iD-oIgPhkeQFk
Я знаю, що це дещо відрізняється від питання щодо ОП, але я думаю, що це все-таки буде корисно багатьом, хто шукав той самий випадок використання, який я шукав.
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
Я вважав це простішим та чистішим.
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
Просто змініть 64, щоб змінити довжину, варіюйте Басейн символів, щоб робити лише альфа-цифрові чисельні або лише цифрові або дивні символи чи що завгодно.