我正在寻找一种在Python中以与os.urandom()
方法类似的方式生成 n 字节的随机字符串的方法,除了提供种子数据生成方法。
到目前为止,我有:
def genRandData(size):
buf = chr(random.randint(0,255))
for i in range(size-1):
buf = buf + chr(random.randint(0,255))
return str(buf)
但是这个功能非常慢,在我的机器上生成一兆字节的数据大约需要1.8秒。有没有办法改善这种情况(或者是种子os.urandom的方式)。
答案 0 :(得分:3)
如果您有numpy
可用,则其random
模块的版本为numpy.random
,其中包含您可能会考虑的此功能:
numpy.random.bytes(length)
非常快:
$ python -mtimeit "import numpy" "numpy.random.bytes(1<<30)"
10 loops, best of 3: 2.19 sec per loop
那是1GiB。
您可以使用numpy.random.seed
播种。
答案 1 :(得分:1)
新答案
重新阅读OP的问题后,我现在明白它是关于原始字节,而不是ascii chars string
那么,这个怎么样?
import random
gl = 0
def randBytes(size):
global gl
nr = bytearray(random.getrandbits(8) for _ in xrange(size))
gl = nr
return
%timeit randBytes(1000000)
1 loops, best of 3: 262 ms per loop
In [27]: gl.__sizeof__()
Out[27]: 1087223
OLD ANSWER HERE
import random
import string
def generateRandomString(size):
return(''.join(random.choice(string.ascii_letters) for i in range(size)))
注意:
一个ascii字符是1个字节。所以“size”表示字符串的长度和字节大小。
您可以使用string.ascii_uppercase或ascii_lowercase来设置大写和小写
random.seed可用于指定种子。
random.seed([X])¶
初始化基本随机数生成器。可选参数x可以 是任何可清洗的对象。如果省略x或None,则为当前系统时间 用来;当前系统时间也用于初始化发电机 首次导入模块时。如果提供随机源 通过操作系统,它们被用来代替系统时间(见 os.urandom()函数有关可用性的详细信息。)
所以你可以:
import random
import string
def generateRandomString(size, seed=None):
if seed != None:
random.seed(seed)
return(''.join(random.choice(string.ascii_letters) for i in range(size)))
时序:
In [30]: %time generateRandomString(1000000)
Wall time: 554 ms
<and then output>
答案 2 :(得分:0)
正如Dan D.所说,让numpy
以C速度在一次命中中生成你的字节将比以Python速度一次生成一个方式更快。
但是,如果您不想使用numpy
,则可以提高代码效率。
通过连接构建字符串,例如buf = buf + chr(random.randint(0,255))
非常慢,因为必须在每个循环上分配新的buf
(请记住,Python字符串是不可变的)。 Python中用于从子字符串构建字符串的常用技术是在列表中累积子字符串,然后使用str.join()
方法将它们组合在一起。
我们还可以通过预生成1字节字符串的列表来节省一点时间,而不是为我们想要的每个字节调用chr()
。
from random import seed, choice
allbytes = [chr(i) for i in range(256)]
def random_bytes(n):
bytes = []
for _ in range(n):
bytes.append(choice(allbytes))
return ''.join(bytes)
我们可以通过使用列表理解来简化这一点并使其稍微更高效:
def random_bytes(n):
return ''.join([choice(allbytes) for _ in range(n)])
根据您打算如何使用这些随机字节,您可能会发现将它们放入bytearray或bytes
对象很有用。
这是基于cristianmtr新答案的变体:
def random_bytes(n):
return bytes(bytearray(getrandbits(8) for _ in xrange(n)))
你可以使用str()
代替bytes()
,但{3}更适合Python 3,因为Python 3字符串是Unicode。
答案 3 :(得分:0)
Python 3.9 random.randbytes
+ random.seed
文档:https://docs.python.org/3.9/library/random.html#random.randbytes
main.py
#!/usr/bin/env python
import random
import sys
random.seed(0)
sys.stdout.buffer.write(random.randbytes(8))
使用固定种子 0 将 8 个伪随机字节写入标准输出:
./main.py | hd
输出:
00000000 cd 07 2c d8 be 6f 9f 62 |..,..o.b|
00000008
它的 definition in CPython 很简单:
def randbytes(self, n):
"""Generate n random bytes."""
return self.getrandbits(n * 8).to_bytes(n, 'little')
此处将其转换为 Bash one liner 并与 /dev/urandom
进行基准比较:Something similar to /dev/urandom with configurable seed?