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

Python 生成可种子数据的随机字符串,python,random,Python,Random,我正在寻找一种在Python中生成n字节随机字符串的方法,其方法与os.uradom()方法类似,只是提供了一种为数据生成种子的方法 到目前为止,我已经: 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) 但是这个功能非常慢,在我的机器上

我正在寻找一种在Python中生成n字节随机字符串的方法,其方法与
os.uradom()
方法类似,只是提供了一种为数据生成种子的方法

到目前为止,我已经:

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.uradom添加种子)。

新答案

在重读了OP的问题之后,我现在明白了,这是关于原始字节,而不是ascii字符字符串

那么,这个怎么样

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
这里的旧答案

import random
import string
def generateRandomString(size):
    return(''.join(random.choice(string.ascii_letters) for i in range(size)))
注:

一个ascii字符是1字节。所以“size”表示字符串的长度和字节大小

您可以使用string.ascii_大写或ascii_小写来表示小写和大写

random.seed可用于指定种子

随机。种子([x])^

初始化基本随机数生成器。可选参数x可以 可以是任何可散列对象。如果省略x或无,则为当前系统时间 使用;当前系统时间也用于初始化发电机 首次导入模块时。如果提供了随机性源 由操作系统使用它们,而不是系统时间(请参阅 有关可用性的详细信息,请参阅os.uradom()函数)

所以你可以:

    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>
[30]中的
:%time GeneratorAndomString(1000000)
墙时间:554毫秒

如果您有可用的
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

$python-mtimeit“import numpy”numpy.random.bytes(1正如Dan D.所说,让
numpy
以C速度一次生成字节要比以python速度一次生成一个快得多

但是,如果您不想使用
numpy
,您可以使代码更高效一些

通过串联构建字符串,例如buf=buf+chr(random.randint(0255))
非常慢,因为必须在每个循环上分配一个新的
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)])

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

以下是一个基于cristianmtr新答案的变体:

def random_bytes(n):
    return bytes(bytearray(getrandbits(8) for _ in xrange(n)))

您可以使用
str()
代替
bytes()
,但是
bytes()
更适合Python 3,因为Python 3字符串是Unicode的。

Python 3.9
random.randbytes
+
random.seed

文件:

main.py

#!/usr/bin/env python
import random
import sys
random.seed(0)
sys.stdout.buffer.write(random.randbytes(8))
将8个伪随机字节写入固定种子为0的标准输出:

./main.py | hd
产出:

00000000  cd 07 2c d8 be 6f 9f 62                           |..,..o.b|
00000008
其内容很简单:

    def randbytes(self, n):
        """Generate n random bytes."""
        return self.getrandbits(n * 8).to_bytes(n, 'little')

在这里,它被转换为Bash one liner,并与
/dev/uradom

1)OP希望所有可能的字节值从
\x00
\xff
,而不仅仅是字母。2)在列表理解中使用
.join()
比在生成器表达式中使用
.join()更有效,因为
.join()
必须扫描它连接的字符串两次:第一次确定总长度,第二次将字符串复制到目标缓冲区。有关详细信息,请参阅Python核心开发人员Raymond Hettinger。嗯,对。没有正确阅读。只是提供了一个新的答案!哇,使用
getrandbits
肯定比我的更快解决方案。但是你为什么要用globals做这些事情呢?只是想在函数完成后能够检查长度和内容。不应该影响每个集合的性能。他们在3.9中添加了一个同名的方法。顺便说一句:
randbytes
,Uradom
的随机性来自随机系统噪声(请参阅),因此允许它可播种是没有意义的。缺乏可播种性对于测试来说很烦人,但它使它成为用于加密目的的一个有用的随机性来源。我想这与你的问题不太相关,但至少它解释了为什么没有办法播种它。:)