Bagus. Buat saja nomor acak sepanjang 30 digit hex dan cetaklah. Jelas saat ditunjukkan. Bagus.
eemz
Menarik, saya agak lupa bahwa Python (dan modul acak) menangani bigints secara native.
wump
3
Lihat jawaban yaronf di bawah ini tentang penggunaan string.hexdigits: stackoverflow.com/a/15462293/311288 " string.hexdigitspengembalian 0123456789abcdefABCDEF(baik huruf kecil dan huruf besar), [...]. Sebagai gantinya, gunakan saja random.choice('0123456789abcdef')."
Thomas
3
Gunakan getrandbitsalih-alih randrangeuntuk membuatnya lebih cepat.
robinst
@bisnis.info memiliki poin yang bagus. '%030x' % random.getrandbits(60)bahkan lebih cepat daripada '%030x' % random.randrange(16**30), kemungkinan karena tidak perlu melakukan konversi apa pun ke / dari orang-orang int besar
Keuntungannya adalah ini mendapatkan keacakan langsung dari OS, yang mungkin lebih aman dan / atau lebih cepat daripada random (), dan Anda tidak perlu melakukan seeding.
itu menarik, dan mungkin pilihan yang baik untuk menghasilkan 30 digit angka hex yang dia inginkan. mungkin bisa menggunakan urandom dan operator slice untuk menghasilkan string alfanumerik juga.
eemz
Saya melihat fungsi lain di binascii, mereka memiliki base64 dan uuencode, tetapi tidak ada cara untuk menghasilkan jenis string pertama yang dia inginkan (base36).
wump
1
Apakah ini cukup acak / unik untuk digunakan dalam, katakanlah, token sesi?
Di Py3.6 +, opsi lain adalah menggunakan secretsmodul standar baru :
>>> import secrets
>>> secrets.token_hex(15)
'8d9bad5b43259c6ee27d9aadc7b832'>>> secrets.token_urlsafe(22) # may include '_-' unclear if that is acceptable'teRq7IqhaRU0S3euX1ji9f58WzUkrg'
import string
import random
lst = [random.choice(string.ascii_letters + string.digits) for n in xrange(30)]
str = "".join(lst)
print str
ocwbKCiuAJLRJgM1bWNV1TPSH0F2Lb
Satu pengguna harus mencoba semua metode pada mesin yang sama untuk mendapatkan baseline yang akurat. Spesifikasi perangkat keras dapat membuat perbedaan besar. >>>> timeit.timeit ("'% 0x'% getrandbits (30 * 4)", "dari impor acak getrandbits") 0.2471246949999113 </pre>
ptay
Terima kasih, ini lebih cepat dari yang lain di atas. %timeit '%030x' % randrange(16**30)memberikan 1000000 loop, terbaik 3: 1,61 µs per loop sementara %timeit '%0x' % getrandbits(30 * 4)memberikan 1000000 loop, terbaik 3: 396 ns per loop
frmdstryr
15
Catatan: random.choice(string.hexdigits)tidak benar, karena string.hexdigitsmengembalikan 0123456789abcdefABCDEF(baik huruf kecil dan huruf besar), jadi Anda akan mendapatkan hasil yang bias, dengan digit hex 'c' dua kali lebih mungkin muncul sebagai digit '7'. Sebagai gantinya, gunakan saja random.choice('0123456789abcdef').
import random
import string
defgenerate_random_key(length):return''.join(random.choice(string.ascii_lowercase + string.digits) for _ in range(length))
print generate_random_key(30)
Ada yang lebih cepat dibandingkan dengan apa yang telah disebutkan jcdyer. Ini membutuhkan ~ 50% dari metode tercepatnya.
from numpy.random.mtrand import RandomState
import binascii
rand = RandomState()
lo = 1000000000000000
hi = 999999999999999999
binascii.b2a_hex(rand.randint(lo, hi, 2).tostring())[:30]
>>> timeit.Timer("binascii.b2a_hex(rand.randint(lo,hi,2).tostring())[:30]", \
... 'from __main__ import lo,hi,rand,binascii').timeit()
1.648831844329834 <-- this is on python 2.6.62.253110885620117 <-- this on python 2.7.5
Anda dapat mengubah parameter ukuran yang diteruskan ke randint (argumen terakhir) untuk memvariasikan panjang keluaran berdasarkan kebutuhan Anda. Jadi, untuk 60 karakter:
Sedikit variasi: di binascii.b2a_hex(np.random.rand(np.ceil(N/16)).view(dtype=int))[:N]mana N=30.
dan-man
@ dan-man Terima kasih untuk metode opsional ini. Namun, saya menemukan bahwa itu menghabiskan setidaknya 5x lebih banyak waktu. Apakah Anda juga menyadarinya?
Ethan
0
menambahkan satu jawaban lagi ke campuran yang bekerja lebih cepat daripada solusi @eemz dan juga sepenuhnya alfanumerik. Perhatikan bahwa ini tidak memberi Anda jawaban heksadesimal.
import random
import string
LETTERS_AND_DIGITS = string.ascii_letters + string.digits
defrandom_choice_algo(width):return''.join(random.choice(LETTERS_AND_DIGITS) for i in range(width))
defrandom_choices_algo(width):return''.join(random.choices(LETTERS_AND_DIGITS, k=width))
print(generate_random_string(10))
# prints "48uTwINW1D"
Ini pasti bukan versi yang paling ringan, tetapi ini acak dan mudah untuk menyesuaikan alfabet / panjang yang Anda inginkan:
import random
defgenerate(random_chars=12, alphabet="0123456789abcdef"):
r = random.SystemRandom()
return''.join([r.choice(alphabet) for i in range(random_chars)])
Jawaban:
Saya mendapat yang lebih cepat untuk keluaran hex. Menggunakan t1 dan t2 yang sama seperti di atas:
>>> t1 = timeit.Timer("''.join(random.choice('0123456789abcdef') for n in xrange(30))", "import random") >>> t2 = timeit.Timer("binascii.b2a_hex(os.urandom(15))", "import os, binascii") >>> t3 = timeit.Timer("'%030x' % random.randrange(16**30)", "import random") >>> for t in t1, t2, t3: ... t.timeit() ... 28.165037870407104 9.0292739868164062 5.2836320400238037
t3
hanya membuat satu panggilan ke modul acak, tidak harus membuat atau membaca daftar, lalu melakukan sisanya dengan pemformatan string.sumber
string.hexdigits
: stackoverflow.com/a/15462293/311288 "string.hexdigits
pengembalian0123456789abcdefABCDEF
(baik huruf kecil dan huruf besar), [...]. Sebagai gantinya, gunakan sajarandom.choice('0123456789abcdef')
."getrandbits
alih-alihrandrange
untuk membuatnya lebih cepat.'%030x' % random.getrandbits(60)
bahkan lebih cepat daripada'%030x' % random.randrange(16**30)
, kemungkinan karena tidak perlu melakukan konversi apa pun ke / dari orang-orang int besar30 digit string hex:
>>> import os,binascii >>> print binascii.b2a_hex(os.urandom(15)) "c84766ca4a3ce52c3602bbf02ad1f7"
Keuntungannya adalah ini mendapatkan keacakan langsung dari OS, yang mungkin lebih aman dan / atau lebih cepat daripada random (), dan Anda tidak perlu melakukan seeding.
sumber
Di Py3.6 +, opsi lain adalah menggunakan
secrets
modul standar baru :>>> import secrets >>> secrets.token_hex(15) '8d9bad5b43259c6ee27d9aadc7b832' >>> secrets.token_urlsafe(22) # may include '_-' unclear if that is acceptable 'teRq7IqhaRU0S3euX1ji9f58WzUkrg'
sumber
import string import random lst = [random.choice(string.ascii_letters + string.digits) for n in xrange(30)] str = "".join(lst) print str ocwbKCiuAJLRJgM1bWNV1TPSH0F2Lb
sumber
random.SystemRandom().choice
Solusi yang secara dramatis lebih cepat daripada yang ada di sini:
timeit("'%0x' % getrandbits(30 * 4)", "from random import getrandbits") 0.8056681156158447
sumber
%timeit '%030x' % randrange(16**30)
memberikan 1000000 loop, terbaik 3: 1,61 µs per loop sementara%timeit '%0x' % getrandbits(30 * 4)
memberikan 1000000 loop, terbaik 3: 396 ns per loopCatatan:
random.choice(string.hexdigits)
tidak benar, karenastring.hexdigits
mengembalikan0123456789abcdefABCDEF
(baik huruf kecil dan huruf besar), jadi Anda akan mendapatkan hasil yang bias, dengan digit hex 'c' dua kali lebih mungkin muncul sebagai digit '7'. Sebagai gantinya, gunakan sajarandom.choice('0123456789abcdef')
.sumber
Metode Lain:
from Crypto import Random import binascii my_hex_value = binascii.hexlify(Random.get_random_bytes(30))
Intinya adalah: nilai byte selalu sama dengan nilai dalam hex .
sumber
fungsi satu baris:
import random import string def generate_random_key(length): return ''.join(random.choice(string.ascii_lowercase + string.digits) for _ in range(length)) print generate_random_key(30)
sumber
In [1]: import random In [2]: hex(random.getrandbits(16)) Out[2]: '0x3b19'
sumber
Secara kebetulan, ini adalah hasil dari penggunaan
timeit
dua pendekatan yang telah disarankan:Menggunakan
random.choice()
:>>> t1 = timeit.Timer("''.join(random.choice(string.hexdigits) for n in xrange(30))", "import random, string") >>> t1.timeit() 69.558588027954102
Menggunakan
binascii.b2a_hex()
:>>> t2 = timeit.Timer("binascii.b2a_hex(os.urandom(15))", "import os, binascii") >>> t2.timeit() 16.288421154022217
sumber
Ada yang lebih cepat dibandingkan dengan apa yang telah disebutkan jcdyer. Ini membutuhkan ~ 50% dari metode tercepatnya.
from numpy.random.mtrand import RandomState import binascii rand = RandomState() lo = 1000000000000000 hi = 999999999999999999 binascii.b2a_hex(rand.randint(lo, hi, 2).tostring())[:30] >>> timeit.Timer("binascii.b2a_hex(rand.randint(lo,hi,2).tostring())[:30]", \ ... 'from __main__ import lo,hi,rand,binascii').timeit() 1.648831844329834 <-- this is on python 2.6.6 2.253110885620117 <-- this on python 2.7.5
Jika Anda ingin di base64:
binascii.b2a_base64(rand.randint(lo, hi, 3).tostring())[:30]
Anda dapat mengubah parameter ukuran yang diteruskan ke randint (argumen terakhir) untuk memvariasikan panjang keluaran berdasarkan kebutuhan Anda. Jadi, untuk 60 karakter:
binascii.b2a_hex(rand.randint(lo, hi, 4).tostring())[:60]
sumber
binascii.b2a_hex(np.random.rand(np.ceil(N/16)).view(dtype=int))[:N]
manaN=30
.menambahkan satu jawaban lagi ke campuran yang bekerja lebih cepat daripada solusi @eemz dan juga sepenuhnya alfanumerik. Perhatikan bahwa ini tidak memberi Anda jawaban heksadesimal.
import random import string LETTERS_AND_DIGITS = string.ascii_letters + string.digits def random_choice_algo(width): return ''.join(random.choice(LETTERS_AND_DIGITS) for i in range(width)) def random_choices_algo(width): return ''.join(random.choices(LETTERS_AND_DIGITS, k=width)) print(generate_random_string(10)) # prints "48uTwINW1D"
hasil patokan cepat
from timeit import timeit from functools import partial arg_width = 10 print("random_choice_algo", timeit(partial(random_choice_algo, arg_width))) # random_choice_algo 8.180561417000717 print("random_choices_algo", timeit(partial(random_choices_algo, arg_width))) # random_choices_algo 3.172438014007639
sumber
Ini pasti bukan versi yang paling ringan, tetapi ini acak dan mudah untuk menyesuaikan alfabet / panjang yang Anda inginkan:
import random def generate(random_chars=12, alphabet="0123456789abcdef"): r = random.SystemRandom() return ''.join([r.choice(alphabet) for i in range(random_chars)])
sumber