生成可播种数据的随机字符串

时间:2015-09-01 10:32:42

标签: python random

我正在寻找一种在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的方式)。

4 个答案:

答案 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)])

根据您打算如何使用这些随机字节,您可能会发现将它们放入bytearraybytes对象很有用。

这是基于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?