确定性并发任务生成伪随机数

时间:2018-11-10 18:37:00

标签: python python-3.x testing random python-asyncio

我有一个协程,它返回伪随机字节列表

import asyncio
import random
import os

async def random_bytes():
    random.seed(a=1234)
    results = []
    for _ in range(0, 128):
        await asyncio.sleep(int(os.urandom(1)[0])/4096)
        results.append(random.getrandbits(8))
    return results

loop = asyncio.get_event_loop()
task_1 = loop.create_task(random_bytes())
print(loop.run_until_complete(task_1))

正如预期的那样,即使每次生成之间的时间间隔不同,此列表在每次运行中也始终相同[基于os.urandom的某些外部熵],伪随机数生成器将使用相同的值。

现在,如果我同时运行其中两个,则创建两个列表...

loop = asyncio.get_event_loop()
task_1 = loop.create_task(random_bytes())
task_2 = loop.create_task(random_bytes())
print(loop.run_until_complete(asyncio.gather(task_1, task_2)))

...列表总是不同的:任务基本上相互干扰,不再确定。

如何生成两个并发的伪随机数任务,其中每个伪随机数列表都具有确定性,就像没有其他任务在运行一样?

[我的用例:使用非确定的时间间隔生成的大量伪随机数来测试并发行为,但希望对于每个任务的每次测试运行,伪随机数本身都相同]

2 个答案:

答案 0 :(得分:2)

来自random module docs

  

此模块提供的功能实际上是random.Random类的隐藏实例的绑定方法。您可以实例化自己的Random实例,以获取不共享状态的生成器。

<h1>s</h1>
<h2>s</h2>
<h3>s</h3>
<button id="mainButton">Remove Headings</button>

答案 1 :(得分:1)

您可以使用random.getstaterandom.setstate,确保在设置状态,生成随机数以及获取状态之间,您不会不要屈服完成另一项任务。

async def random_bytes():
    random.seed(a=1234)
    state = random.getstate()
    results = []
    for _ in range(0, 128):
        await asyncio.sleep(int(os.urandom(1)[0])/4096)
        random.setstate(state)
        results.append(random.getrandbits(8))
        state = random.getstate()
    return results