Ini adalah pertanyaan yang sangat populer. Saya berharap seorang ahli akan menambahkan pandangannya tentang keunikan angka acak ini untuk 3 jawaban teratas yaitu probabilitas tabrakan untuk rentang ukuran string, katakanlah dari 6 hingga 16.
pengguna
8
@buffer Sangat mudah untuk menghitung jumlah kombinasi yang memungkinkan. 10 angka + 26 huruf = 36 karakter yang memungkinkan, dengan kekuatan 6 (panjang string) sama dengan sekitar dua miliar. Aturan praktis saya untuk nilai acak adalah "jika saya menghasilkan nilai untuk setiap manusia di Bumi, berapa banyak nilai yang dapat mereka miliki masing-masing?". Dalam hal ini yang kurang dari satu nilai per orang, jadi jika ini untuk mengidentifikasi pengguna atau objek, terlalu sedikit karakter. Salah satu alternatifnya adalah dengan menambahkan huruf kecil, yang membuat Anda mencapai 62 ^ 6 = hampir 57 miliar nilai unik.
Blixt
1
Dan sementara itu mungkin tampak konyol untuk memikirkan populasi dunia, itu hanya karena Anda ingin penyangga besar untuk potensi tabrakan. Lihat masalah ulang tahun: en.wikipedia.org/wiki/Birthday_problem
Kemudian kami menggunakan pemahaman daftar untuk membuat daftar elemen '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']
Pada contoh di atas, kami menggunakan [untuk membuat daftar, tetapi kami tidak diid_generator fungsi sehingga Python tidak membuat daftar dalam memori, tetapi menghasilkan elemen dengan cepat, satu per satu (lebih lanjut tentang ini di sini ).
Alih-alih meminta untuk membuat 'n' kali string elem , kami akan meminta Python untuk membuat 'n' kali karakter acak, diambil dari urutan karakter:
Oleh karena itu random.choice(chars) for _ in range(size)benar-benar membuat urutan sizekarakter. Karakter yang dipilih secara acak dari 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']
Kemudian kita hanya bergabung dengan mereka dengan string kosong sehingga urutannya menjadi string:
>>>''.join(['a','b','b'])'abb'>>>[random.choice('abcde')for _ in range(3)]['d','c','b']>>>''.join(random.choice('abcde')for _ in range(3))'dac'
@ jorelli: Ini bukan pemahaman daftar; itu ekspresi generator.
Ignacio Vazquez-Abrams
2
@ joreilli: Saya menambahkan catatan singkat tentang ini di jawaban, dan tautan ke jawaban yang lebih terperinci tentang iterable, daftar pemahaman, generator, dan akhirnya kata kunci hasil.
e-satis
1
Saya akan ganti rangedengan xrange.
Dr. Jan-Philip Gehrcke
1
Sangat berguna. Menariknya, Django menggunakan kode ini untuk menghasilkan kata sandi & token CSRF. Meskipun Anda harus mengganti randomdengan random.SystemRandom(): github.com/django/django/blob/…
pengguna
1
@ Chiel92, random.samplemembuat sampel tanpa penggantian, dengan kata lain, tanpa kemungkinan untuk mengulangi karakter, yang tidak ada dalam persyaratan OP. Saya tidak berpikir itu akan diinginkan untuk sebagian besar aplikasi.
ontologis
557
Pertanyaan Stack Overflow ini adalah hasil Google teratas saat ini untuk "string acak Python". Jawaban teratas saat ini adalah:
''.join(random.choice(string.ascii_uppercase + string.digits)for _ in range(N))
Ini adalah metode yang sangat baik, tetapi PRNG secara acak tidak aman secara kriptografis. Saya berasumsi banyak orang yang meneliti pertanyaan ini ingin menghasilkan string acak untuk enkripsi atau kata sandi. Anda dapat melakukan ini dengan aman dengan membuat perubahan kecil pada kode di atas:
''.join(random.SystemRandom().choice(string.ascii_uppercase + string.digits)for _ in range(N))
Menggunakan random.SystemRandom()alih-alih hanya menggunakan / dev / urandom secara acak pada mesin * nix dan CryptGenRandom()di Windows. Ini adalah PRNG yang aman secara kriptografis. Menggunakan random.choicealih-alih random.SystemRandom().choicedalam aplikasi yang membutuhkan PRNG aman dapat berpotensi menghancurkan, dan mengingat popularitas pertanyaan ini, saya yakin kesalahan telah dilakukan berkali-kali.
Jika Anda menggunakan python3.6 atau lebih baru, Anda bisa menggunakan modul rahasia baru seperti yang disebutkan dalam jawaban MSeifert :
''.join(secrets.choice(string.ascii_uppercase + string.digits)for _ in range(N))
Ya, pustaka standar resmi untuk randomtelah memperingatkan ini: " Peringatan : Generator pseudo-acak dari modul ini tidak boleh digunakan untuk tujuan keamanan. Gunakan os.urandom () atau SystemRandom jika Anda memerlukan generator nomor pseudo-acak yang aman secara kriptografi. " Inilah refnya : random.SystemRandom dan os.urandom
lord63. j
4
Jawaban yang bagus Catatan kecil: Anda mengubahnya string.uppercaseyang dapat menyebabkan hasil yang tidak terduga tergantung pada set lokal. Menggunakan string.ascii_uppercase(atau string.ascii_letters + string.digitsuntuk base62 bukannya base36) lebih aman dalam kasus-kasus di mana encoding terlibat.
Blixt
catatan kecil - lebih baik digunakan xrangedaripada rangeyang terakhir menghasilkan daftar dalam memori, sementara yang pertama membuat iterator.
guyarad
2
Apakah sengatan acak akan selalu menjadi unik? saya ingin menggunakan kunci utama.
shakthydoss
3
@shakthydoss: tidak. Ini dapat mengembalikan "AAA000", yang merupakan string acak, dan "AAA000" berikutnya, yang juga merupakan string acak. Anda harus secara eksplisit menambahkan tanda centang untuk keunikan.
usr2564301
189
Cukup gunakan Python builtin uuid:
Jika UUID tidak apa-apa untuk keperluan Anda, gunakan paket uuid bawaan .
Solusi Satu Jalur:
import uuid; uuid.uuid4().hex.upper()[0:6]
Dalam Versi Kedalaman:
Contoh:
import uuid
uuid.uuid4()#uuid4 => full random uuid# Outputs something like: UUID('0172fc9a-1dac-4414-b88d-6b9a6feb91ea')
Jika Anda benar-benar membutuhkan format Anda (misalnya, "6U1S75"), Anda dapat melakukannya seperti ini:
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
+1 Untuk berpikir di balik pertanyaan. Mungkin Anda bisa menjelaskan secara singkat perbedaan antara uuid1 dan uuid4.
Thomas Ahle
1
Jika saya melakukan uuid1 tiga kali berturut-turut, saya mendapatkan: d161fd16-ab0f-11e3-9314-00259073e4a8, d3535b56-ab0f-11e3-9314-00259073e4a8, d413be32-ab0f-11e3-9314-00259073e4 8 karakter pertama berbeda dan sisanya sama). Ini bukan kasus dengan uuid4
Chase Roberts
9
uui1: Hasilkan UUID dari ID host, nomor urut, dan waktu saat ini. uuid4: Hasilkan UUID acak.
Bijan
7
Jika Anda ingin melewatkan string casting & hyphen replacing, Anda bisa memanggil my_uuid.get_hex () atau uuid.uuid4 (). Get_hex () dan itu akan mengembalikan string yang dihasilkan dari uuid yang tidak memiliki tanda hubung.
dshap
8
Apakah ide yang baik untuk memotong UUID? Tergantung pada seberapa kecilnya string_length, kemungkinan tabrakan bisa menjadi perhatian.
pengguna
44
Cara yang lebih sederhana, lebih cepat tetapi sedikit kurang acak adalah dengan menggunakan random.samplealih-alih memilih setiap huruf secara terpisah, Jika n-pengulangan diperbolehkan, perbesar basis acak Anda dengan n kali mis
import random
import string
char_set = string.ascii_uppercase + string.digits
print''.join(random.sample(char_set*6,6))
Catatan: random.sample mencegah penggunaan kembali karakter, mengalikan ukuran dari set karakter memungkinkan beberapa kali pengulangan, tetapi mereka masih lebih kecil kemungkinannya daripada pilihan acak murni. Jika kita menggunakan string dengan panjang 6, dan kita memilih 'X' sebagai karakter pertama, dalam contoh pilihan, peluang mendapatkan 'X' untuk karakter kedua sama dengan peluang mendapatkan 'X' sebagai karakter pertama. karakter pertama. Dalam implementasi random.sample, peluang mendapatkan 'X' sebagai karakter berikutnya hanya 6/7 peluang untuk mendapatkannya sebagai karakter pertama
Cara ini tidak buruk, tetapi tidak secara acak memilih setiap karakter secara terpisah, karena sampleAnda tidak akan pernah mendapatkan karakter yang sama terdaftar dua kali. Juga tentu saja akan gagal Nlebih tinggi dari 36.
bobince
untuk kasus penggunaan yang diberikan (jika tidak ada pengulangan ok) saya akan mengatakan itu masih solusi terbaik.
Anurag Uniyal
3
Salah satu contoh memiliki pengulangan, jadi saya ragu dia ingin melarang pengulangan.
Mark Byers
5
Jika random.sample mencegah penggunaan kembali karakter, mengalikan ukuran dari set karakter membuat beberapa pengulangan dimungkinkan , tetapi mereka masih lebih kecil kemungkinannya maka mereka berada dalam pilihan acak murni. Jika kita menggunakan string dengan panjang 6, dan kita memilih 'X' sebagai karakter pertama, dalam contoh pilihan, peluang mendapatkan 'X' untuk karakter kedua sama dengan peluang mendapatkan 'X' sebagai karakter pertama. karakter pertama. Dalam implementasi random.sample, peluang mendapatkan 'X' sebagai karakter berikutnya hanya 5/6 peluang untuk mendapatkannya sebagai karakter pertama.
pcurry
1
Peluang mendapatkan karakter tertentu berulang menurun saat Anda bergerak melalui string yang dihasilkan. Menghasilkan string 6 karakter dari 26 huruf besar ditambah 10 digit, secara acak memilih masing-masing karakter, setiap string tertentu terjadi dengan frekuensi 1 / (36 ^ 6). Peluang menghasilkan 'FU3WYE' dan 'XXXXXX' adalah sama. Dalam implementasi sampel, peluang menghasilkan 'XXXXXX' adalah (1 / (36 ^ 6)) * ((6/6) * (5/6) * (4/6) * (3/6) * (3/6) * (2 / 6) * (1/6)) karena fitur non-penggantian random.sample. 'XXXXXX' adalah 324 kali lebih kecil kemungkinannya dalam implementasi sampel.
pcurry
32
import uuid
lowercase_str = uuid.uuid4().hex
lowercase_str adalah nilai acak seperti 'cea8b32e00934aaea8c005a35d85a5c0'
uppercase_str = lowercase_str.upper()
uppercase_str adalah 'CEA8B32E00934AAEA8C005A35D85A5C0'
@Yajo: tidak, Anda tidak ingin mengiris nilai hex. Anda menghapus entropi dibandingkan dengan urutan huruf dan digit huruf besar. Mungkin base32-encode nilainya (entropi sedikit berkurang, dari 36 ** n menjadi 32 ** n, masih lebih baik dari 16 ** n).
Martijn Pieters
19
Cara yang lebih cepat, lebih mudah, dan lebih fleksibel untuk melakukan ini adalah dengan menggunakan strgenmodul ( pip install StringGenerator).
Hasilkan string acak 6-karakter dengan huruf besar dan angka:
''.join(random.choice(string.ascii_uppercase + string.digits)for _ in range(N))
mungkin tidak memiliki angka (atau huruf besar) di dalamnya.
strgenlebih cepat dalam waktu pengembang daripada solusi di atas. Solusi dari Ignacio adalah performa run-time tercepat dan merupakan jawaban yang tepat menggunakan Python Standard Library. Tetapi Anda tidak akan pernah menggunakannya dalam bentuk itu. Anda akan ingin menggunakan SystemRandom (atau fallback jika tidak tersedia), pastikan set karakter yang diperlukan diwakili, gunakan unicode (atau tidak), pastikan invokasi berturut-turut menghasilkan string yang unik, gunakan subset dari salah satu kelas karakter modul string, dll. Ini semua membutuhkan lebih banyak kode daripada jawaban yang diberikan. Berbagai upaya untuk menggeneralisasi suatu solusi semuanya memiliki keterbatasan yang dapat dipecahkan dengan kekuatan yang lebih besar dan daya ekspresif menggunakan bahasa templat sederhana.
Dari Python 3.6 pada Anda harus menggunakan secretsmodul jika Anda membutuhkannya aman secara kriptografis, bukan randommodul (jika tidak, jawaban ini identik dengan salah satu dari @Ignacio Vazquez-Abrams):
from secrets import choice
import string
''.join([choice(string.ascii_uppercase + string.digits)for _ in range(N)])
Satu catatan tambahan: pemahaman daftar lebih cepat dalam hal str.joindaripada menggunakan ekspresi generator!
Ini bagus, meskipun hanya akan menggunakan 'AF' dan bukan 'A-Z'. Juga, kode menjadi sedikit kurang baik ketika parametrize N.
Thomas Ahle
9
Jika Anda membutuhkan string acak daripada pseudo acak , Anda harus menggunakan os.urandomsebagai sumber
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))
Bagaimana os.urandomtidak pseudo acak? Mungkin menggunakan algoritma yang lebih baik untuk menghasilkan angka yang lebih acak, tetapi itu masih pseudo acak.
Tyilo
@ Tyilo, saya menyadari perbedaan antara /dev/randomdan /dev/urandom. Masalahnya adalah bahwa /dev/randomblok ketika tidak ada cukup entropi yang membatasi kegunaannya. Untuk satu kali pad/dev/urandom tidak cukup bagus, tapi saya pikir ini lebih baik daripada pseudo random di sini.
John La Rooy
1
Saya akan mengatakan bahwa keduanya /dev/randomdan /dev/urandompseudo acak, tetapi mungkin tergantung pada definisi Anda.
Tyilo
9
Saya pikir belum ada yang menjawab ini lol! Tapi hei, ini dia sendiri:
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))],"")
Saya tidak akan memilih ini, tapi saya pikir itu terlalu rumit untuk tugas yang sederhana. Ekspresi balik adalah monster. Sederhana lebih baik daripada kompleks.
Carl Smith
12
@CarlSmith, benar solusi saya tampaknya sedikit berlebihan untuk tugas itu, tetapi saya menyadari solusi sederhana lainnya, dan hanya ingin menemukan rute alternatif untuk jawaban yang baik. Tanpa kebebasan, kreativitas berada dalam bahaya, jadi saya teruskan dan mempostingnya.
nemesisfixx
7
Metode ini sedikit lebih cepat, dan sedikit lebih menjengkelkan, daripada metode random.choice () yang diposting Ignacio.
Itu mengambil keuntungan dari sifat algoritma pseudo-acak, dan bank pada bitwise dan dan bergeser menjadi lebih cepat daripada menghasilkan angka acak baru untuk setiap karakter.
# 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 >>5return''.join(_ALPHABET[x]for x in chop(random.getrandbits(size *5))).ljust(size,'A')
... buat generator yang mengeluarkan angka 5 bit sekaligus 0..31 hingga tidak ada yang tersisa
... gabung () hasil generator pada nomor acak dengan bit yang tepat
Dengan Timeit, untuk string 32-karakter, waktunya adalah:
Namun varian ini akan memaksa semua karakter berbeda. Dan itu tidak akan berfungsi jika N lebih besar dari len (string.ascii_uppercase + string.digits)
MarSoft
3
Bagi Anda yang menikmati python fungsional:
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))))
Ini menghasilkan iterator [tak terbatas] tidak terbatas, dari urutan acak yang bergabung, dengan terlebih dahulu menghasilkan urutan tak terbatas dari simbol yang dipilih secara acak dari kumpulan pemberian, kemudian memecah urutan ini menjadi bagian panjang yang kemudian bergabung, itu harus bekerja dengan urutan yang mendukung getitem , secara default itu hanya menghasilkan urutan acak huruf alfanumerik, meskipun Anda dapat dengan mudah memodifikasi untuk menghasilkan hal-hal lain:
Seperti yang disebutkan orang lain jika Anda membutuhkan keamanan lebih maka setel fungsi pilih yang sesuai:
>>>from random importSystemRandom>>> rand_strs = irand_seqs(select=SystemRandom().choice)'QsaDxQ'
pemilih default adalah choiceyang dapat memilih simbol yang sama beberapa kali untuk setiap chunk, jika bukan Anda ingin anggota yang sama dipilih paling banyak satu kali untuk setiap chunk maka, satu kemungkinan penggunaan:
kami gunakan samplesebagai pemilih kami, untuk melakukan pemilihan lengkap, sehingga potongan sebenarnya panjang 1, dan untuk bergabung kami hanya memanggil nextyang mengambil potongan yang dihasilkan sepenuhnya berikutnya, diberikan contoh ini tampaknya sedikit rumit dan ...
(1) Ini akan memberi Anda semua huruf besar dan angka:
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) Jika nanti Anda ingin memasukkan huruf kecil ke dalam kunci Anda, maka ini juga akan berfungsi:
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
>>> 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'
The random.choicefungsi mengambil entri acak dalam daftar. Anda juga membuat daftar sehingga Anda dapat menambahkan karakter dalam forpernyataan. Pada str akhirnya adalah [ 't', 'm', '2', 'J', 'U', 'Q', '0', '4', 'C', 'K'], tetapi str = "".join(str)membutuhkan peduli itu, meninggalkanmu 'tm2JUQ04CK'.
Bagus, tetapi Anda bisa menggunakan range(num)sebagai gantinya, dan str bisa menjadi string 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
Meskipun kode ini dapat menjawab pertanyaan, memberikan konteks tambahan tentang alasannya dan / atau bagaimana ia menjawab pertanyaan akan secara signifikan meningkatkan nilai jangka panjangnya. Harap edit jawaban Anda untuk menambahkan beberapa penjelasan.
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="")
Di sini panjang string dapat diubah dalam untuk loop yaitu untuk i dalam kisaran (1, panjang) Ini adalah algoritma sederhana yang mudah dimengerti. menggunakan daftar sehingga Anda dapat membuang karakter yang tidak Anda butuhkan.
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
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)))
Keluaran:
Method1 vs Method2, run 10 times each.100 characters:0.001411s:0.00179s
ratio =1.0:1.271000 characters:0.013857s:0.017603s
ratio =1.0:1.2710000 characters:0.13426s:0.151169s
ratio =1.0:1.1350000 characters:0.709403s:0.855136s
ratio =1.0:1.21100000 characters:1.360735s:1.674584s
ratio =1.0:1.23500000 characters:6.754923s:7.160508s
ratio =1.0:1.061000000 characters:11.232965s:14.223914s
ratio =1.0:1.27
Saya telah memeriksa hampir semua jawaban tetapi tidak ada yang terlihat lebih mudah. Saya sarankan Anda untuk mencoba passgen perpustakaan yang umumnya digunakan untuk membuat kata sandi acak.
Anda dapat membuat string acak dari panjang, tanda baca, digit, huruf, dan case pilihan Anda.
Saya melihat jawaban yang berbeda dan meluangkan waktu untuk membaca dokumentasi rahasia
Modul rahasia digunakan untuk menghasilkan angka acak kriptografis yang kuat yang cocok untuk mengelola data seperti kata sandi, otentikasi akun, token keamanan, dan rahasia terkait.
Secara khusus, rahasia harus digunakan dalam preferensi ke generator nomor pseudo-acak default dalam modul acak, yang dirancang untuk pemodelan dan simulasi, bukan keamanan atau kriptografi.
Melihat lebih dalam apa yang ditawarkan, saya menemukan fungsi yang sangat berguna jika Anda ingin meniru ID seperti ID Google Drive:
secrets.token_urlsafe ([nbytes = None])
Mengembalikan string teks URL-safe acak, yang berisi nbytes byte acak. Teks ini disandikan Base64, sehingga rata-rata setiap byte menghasilkan sekitar 1,3 karakter . Jika nbytes Tidak Ada atau tidak disediakan, standar yang wajar digunakan.
Gunakan dengan cara berikut:
import secrets
import math
def id_generator():
id = secrets.token_urlsafe(math.floor(32/1.3))return id
print(id_generator())
Keluarkan id panjang 32 karakter:
joXR8dYbBDAHpVs5ci6iD-oIgPhkeQFk
Saya tahu ini sedikit berbeda dari pertanyaan OP tapi saya berharap itu akan tetap bermanfaat bagi banyak orang yang mencari kasus penggunaan yang sama yang saya cari.
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
Cukup ubah 64 untuk memvariasikan panjangnya, variasikan CharacterPool untuk melakukan hanya alpha alpha numeric atau numeric saja atau karakter aneh atau apa pun yang Anda inginkan.
Jawaban:
Jawab dalam satu baris:
atau bahkan lebih pendek dimulai dengan Python 3.6 menggunakan
random.choices()
:Versi yang lebih aman secara kriptografis; lihat https://stackoverflow.com/a/23728630/2213647 :
Secara rinci, dengan fungsi bersih untuk digunakan kembali:
Bagaimana cara kerjanya ?
Kami mengimpor
string
, modul yang berisi urutan karakter ASCII umum, danrandom
, modul yang berkaitan dengan generasi acak.string.ascii_uppercase + string.digits
baru saja menyatukan daftar karakter yang mewakili karakter dan huruf ASCII huruf besar:Kemudian kami menggunakan pemahaman daftar untuk membuat daftar elemen 'n':
Pada contoh di atas, kami menggunakan
[
untuk membuat daftar, tetapi kami tidak diid_generator
fungsi sehingga Python tidak membuat daftar dalam memori, tetapi menghasilkan elemen dengan cepat, satu per satu (lebih lanjut tentang ini di sini ).Alih-alih meminta untuk membuat 'n' kali string
elem
, kami akan meminta Python untuk membuat 'n' kali karakter acak, diambil dari urutan karakter:Oleh karena itu
random.choice(chars) for _ in range(size)
benar-benar membuat urutansize
karakter. Karakter yang dipilih secara acak darichars
:Kemudian kita hanya bergabung dengan mereka dengan string kosong sehingga urutannya menjadi string:
sumber
range
denganxrange
.random
denganrandom.SystemRandom()
: github.com/django/django/blob/…random.sample
membuat sampel tanpa penggantian, dengan kata lain, tanpa kemungkinan untuk mengulangi karakter, yang tidak ada dalam persyaratan OP. Saya tidak berpikir itu akan diinginkan untuk sebagian besar aplikasi.Pertanyaan Stack Overflow ini adalah hasil Google teratas saat ini untuk "string acak Python". Jawaban teratas saat ini adalah:
Ini adalah metode yang sangat baik, tetapi PRNG secara acak tidak aman secara kriptografis. Saya berasumsi banyak orang yang meneliti pertanyaan ini ingin menghasilkan string acak untuk enkripsi atau kata sandi. Anda dapat melakukan ini dengan aman dengan membuat perubahan kecil pada kode di atas:
Menggunakan
random.SystemRandom()
alih-alih hanya menggunakan / dev / urandom secara acak pada mesin * nix danCryptGenRandom()
di Windows. Ini adalah PRNG yang aman secara kriptografis. Menggunakanrandom.choice
alih-alihrandom.SystemRandom().choice
dalam aplikasi yang membutuhkan PRNG aman dapat berpotensi menghancurkan, dan mengingat popularitas pertanyaan ini, saya yakin kesalahan telah dilakukan berkali-kali.Jika Anda menggunakan python3.6 atau lebih baru, Anda bisa menggunakan modul rahasia baru seperti yang disebutkan dalam jawaban MSeifert :
Dokumen modul juga membahas cara mudah untuk menghasilkan token aman dan praktik terbaik .
sumber
random
telah memperingatkan ini: " Peringatan : Generator pseudo-acak dari modul ini tidak boleh digunakan untuk tujuan keamanan. Gunakan os.urandom () atau SystemRandom jika Anda memerlukan generator nomor pseudo-acak yang aman secara kriptografi. " Inilah refnya : random.SystemRandom dan os.urandomstring.uppercase
yang dapat menyebabkan hasil yang tidak terduga tergantung pada set lokal. Menggunakanstring.ascii_uppercase
(ataustring.ascii_letters + string.digits
untuk base62 bukannya base36) lebih aman dalam kasus-kasus di mana encoding terlibat.xrange
daripadarange
yang terakhir menghasilkan daftar dalam memori, sementara yang pertama membuat iterator.Cukup gunakan Python builtin uuid:
Jika UUID tidak apa-apa untuk keperluan Anda, gunakan paket uuid bawaan .
Solusi Satu Jalur:
import uuid; uuid.uuid4().hex.upper()[0:6]
Dalam Versi Kedalaman:
Contoh:
Jika Anda benar-benar membutuhkan format Anda (misalnya, "6U1S75"), Anda dapat melakukannya seperti ini:
sumber
string_length
, kemungkinan tabrakan bisa menjadi perhatian.Cara yang lebih sederhana, lebih cepat tetapi sedikit kurang acak adalah dengan menggunakan
random.sample
alih-alih memilih setiap huruf secara terpisah, Jika n-pengulangan diperbolehkan, perbesar basis acak Anda dengan n kali misCatatan: random.sample mencegah penggunaan kembali karakter, mengalikan ukuran dari set karakter memungkinkan beberapa kali pengulangan, tetapi mereka masih lebih kecil kemungkinannya daripada pilihan acak murni. Jika kita menggunakan string dengan panjang 6, dan kita memilih 'X' sebagai karakter pertama, dalam contoh pilihan, peluang mendapatkan 'X' untuk karakter kedua sama dengan peluang mendapatkan 'X' sebagai karakter pertama. karakter pertama. Dalam implementasi random.sample, peluang mendapatkan 'X' sebagai karakter berikutnya hanya 6/7 peluang untuk mendapatkannya sebagai karakter pertama
sumber
sample
Anda tidak akan pernah mendapatkan karakter yang sama terdaftar dua kali. Juga tentu saja akan gagalN
lebih tinggi dari36
.lowercase_str
adalah nilai acak seperti'cea8b32e00934aaea8c005a35d85a5c0'
uppercase_str
adalah'CEA8B32E00934AAEA8C005A35D85A5C0'
sumber
uppercase_str[:N+1]
Cara yang lebih cepat, lebih mudah, dan lebih fleksibel untuk melakukan ini adalah dengan menggunakan
strgen
modul (pip install StringGenerator
).Hasilkan string acak 6-karakter dengan huruf besar dan angka:
Dapatkan daftar unik:
Jaminan satu karakter "spesial" dalam string:
Warna HTML acak:
dll.
Kita perlu menyadari bahwa ini:
mungkin tidak memiliki angka (atau huruf besar) di dalamnya.
strgen
lebih cepat dalam waktu pengembang daripada solusi di atas. Solusi dari Ignacio adalah performa run-time tercepat dan merupakan jawaban yang tepat menggunakan Python Standard Library. Tetapi Anda tidak akan pernah menggunakannya dalam bentuk itu. Anda akan ingin menggunakan SystemRandom (atau fallback jika tidak tersedia), pastikan set karakter yang diperlukan diwakili, gunakan unicode (atau tidak), pastikan invokasi berturut-turut menghasilkan string yang unik, gunakan subset dari salah satu kelas karakter modul string, dll. Ini semua membutuhkan lebih banyak kode daripada jawaban yang diberikan. Berbagai upaya untuk menggeneralisasi suatu solusi semuanya memiliki keterbatasan yang dapat dipecahkan dengan kekuatan yang lebih besar dan daya ekspresif menggunakan bahasa templat sederhana.Ada di PyPI:
Pengungkapan: Saya penulis modul strgen.
sumber
Dari Python 3.6 pada Anda harus menggunakan
secrets
modul jika Anda membutuhkannya aman secara kriptografis, bukanrandom
modul (jika tidak, jawaban ini identik dengan salah satu dari @Ignacio Vazquez-Abrams):Satu catatan tambahan: pemahaman daftar lebih cepat dalam hal
str.join
daripada menggunakan ekspresi generator!sumber
Berdasarkan jawaban Stack Overflow lainnya, Cara paling ringan untuk membuat string acak dan angka heksadesimal acak , versi yang lebih baik daripada jawaban yang diterima adalah:
lebih cepat.
sumber
N
.Jika Anda membutuhkan string acak daripada pseudo acak , Anda harus menggunakan
os.urandom
sebagai sumbersumber
os.urandom
tidak pseudo acak? Mungkin menggunakan algoritma yang lebih baik untuk menghasilkan angka yang lebih acak, tetapi itu masih pseudo acak./dev/random
dan/dev/urandom
. Masalahnya adalah bahwa/dev/random
blok ketika tidak ada cukup entropi yang membatasi kegunaannya. Untuk satu kali pad/dev/urandom
tidak cukup bagus, tapi saya pikir ini lebih baik daripada pseudo random di sini./dev/random
dan/dev/urandom
pseudo acak, tetapi mungkin tergantung pada definisi Anda.Saya pikir belum ada yang menjawab ini lol! Tapi hei, ini dia sendiri:
sumber
Metode ini sedikit lebih cepat, dan sedikit lebih menjengkelkan, daripada metode random.choice () yang diposting Ignacio.
Itu mengambil keuntungan dari sifat algoritma pseudo-acak, dan bank pada bitwise dan dan bergeser menjadi lebih cepat daripada menghasilkan angka acak baru untuk setiap karakter.
... buat generator yang mengeluarkan angka 5 bit sekaligus 0..31 hingga tidak ada yang tersisa
... gabung () hasil generator pada nomor acak dengan bit yang tepat
Dengan Timeit, untuk string 32-karakter, waktunya adalah:
... tetapi untuk 64 string karakter, randbits kalah;)
Saya mungkin tidak akan pernah menggunakan pendekatan ini dalam kode produksi kecuali saya benar-benar tidak menyukai rekan kerja saya.
sunting: diperbarui sesuai dengan pertanyaan (hanya huruf besar dan digit), dan gunakan operator bitwise & dan >> alih-alih% dan //
sumber
Saya akan melakukannya dengan cara ini:
Atau hanya:
sumber
Gunakan fungsi random.choice () Numpy
Dokumentasi ada di sini http://docs.scipy.org/doc/numpy-1.10.0/reference/generated/numpy.random.choice.html
sumber
Terkadang 0 (nol) & O (huruf O) dapat membingungkan. Jadi saya gunakan
sumber
Logika berikut masih menghasilkan 6 karakter sampel acak
Tidak perlu dikalikan 6
sumber
Bagi Anda yang menikmati python fungsional:
Ini menghasilkan iterator [tak terbatas] tidak terbatas, dari urutan acak yang bergabung, dengan terlebih dahulu menghasilkan urutan tak terbatas dari simbol yang dipilih secara acak dari kumpulan pemberian, kemudian memecah urutan ini menjadi bagian panjang yang kemudian bergabung, itu harus bekerja dengan urutan yang mendukung getitem , secara default itu hanya menghasilkan urutan acak huruf alfanumerik, meskipun Anda dapat dengan mudah memodifikasi untuk menghasilkan hal-hal lain:
misalnya untuk menghasilkan tupel angka acak:
jika Anda tidak ingin menggunakan generasi berikutnya, Anda bisa membuatnya bisa dipanggil:
jika Anda ingin membuat urutan dengan cepat, cukup setel join ke identitas.
Seperti yang disebutkan orang lain jika Anda membutuhkan keamanan lebih maka setel fungsi pilih yang sesuai:
pemilih default adalah
choice
yang dapat memilih simbol yang sama beberapa kali untuk setiap chunk, jika bukan Anda ingin anggota yang sama dipilih paling banyak satu kali untuk setiap chunk maka, satu kemungkinan penggunaan:kami gunakan
sample
sebagai pemilih kami, untuk melakukan pemilihan lengkap, sehingga potongan sebenarnya panjang 1, dan untuk bergabung kami hanya memanggilnext
yang mengambil potongan yang dihasilkan sepenuhnya berikutnya, diberikan contoh ini tampaknya sedikit rumit dan ...sumber
(1) Ini akan memberi Anda semua huruf besar dan angka:
(2) Jika nanti Anda ingin memasukkan huruf kecil ke dalam kunci Anda, maka ini juga akan berfungsi:
sumber
ini adalah tanggapan Anurag Uniyal dan sesuatu yang sedang saya kerjakan sendiri.
sumber
The
random.choice
fungsi mengambil entri acak dalam daftar. Anda juga membuat daftar sehingga Anda dapat menambahkan karakter dalamfor
pernyataan. Pada str akhirnya adalah [ 't', 'm', '2', 'J', 'U', 'Q', '0', '4', 'C', 'K'], tetapistr = "".join(str)
membutuhkan peduli itu, meninggalkanmu'tm2JUQ04CK'
.Semoga ini membantu!
sumber
range(num)
sebagai gantinya, dan str bisa menjadi stringstr += random.choice(chars)
.sumber
Di sini panjang string dapat diubah dalam untuk loop yaitu untuk i dalam kisaran (1, panjang) Ini adalah algoritma sederhana yang mudah dimengerti. menggunakan daftar sehingga Anda dapat membuang karakter yang tidak Anda butuhkan.
sumber
Yang sederhana:
sumber
Saya ingin menyarankan Anda opsi selanjutnya:
Mode paranoic:
sumber
Dua metode:
Keluaran:
Kinerja metode pertama lebih baik.
sumber
Saya telah memeriksa hampir semua jawaban tetapi tidak ada yang terlihat lebih mudah. Saya sarankan Anda untuk mencoba passgen perpustakaan yang umumnya digunakan untuk membuat kata sandi acak.
Anda dapat membuat string acak dari panjang, tanda baca, digit, huruf, dan case pilihan Anda.
Berikut kode untuk kasus Anda:
sumber
Hasilkan ID 16-byte acak yang berisi huruf besar, angka, '_' dan '-'
os.urandom(16).translate((f'{string.ascii_letters}{string.digits}-_'*4).encode('ascii'))
sumber
Saya melihat jawaban yang berbeda dan meluangkan waktu untuk membaca dokumentasi rahasia
Melihat lebih dalam apa yang ditawarkan, saya menemukan fungsi yang sangat berguna jika Anda ingin meniru ID seperti ID Google Drive:
Gunakan dengan cara berikut:
Keluarkan id panjang 32 karakter:
Saya tahu ini sedikit berbeda dari pertanyaan OP tapi saya berharap itu akan tetap bermanfaat bagi banyak orang yang mencari kasus penggunaan yang sama yang saya cari.
sumber
sumber
Saya menemukan ini lebih sederhana dan lebih bersih.
Cukup ubah 64 untuk memvariasikan panjangnya, variasikan CharacterPool untuk melakukan hanya alpha alpha numeric atau numeric saja atau karakter aneh atau apa pun yang Anda inginkan.
sumber