rgalhama
rgalhama

Reputation: 314

Is there a good way to share the seed of random between modules (in python)?

I have a project with different main files (for different simulations). When I run one of the mainfiles, it should set a seed to random (and numpy.random), and all the modules in the project should use that seed.

I don't find a good way to do this. I have a file globals.py with this:

import random

myRandom=None


def initSeed(seed):
    global myRandom
    myRandom =random.Random(seed)

then from a main I do:

if __name__ == "__main__":

    seed=10
    globals.initSeed(seed)
...

Then in the modules that main calls, I do:

from globals import myRandom

But myRandom has the value None in the module (even though I modified it in main!). Why, and how to fix it? Is there a nicer way?

Upvotes: 9

Views: 4307

Answers (2)

jDo
jDo

Reputation: 4010

I'd use a file to avoid global and to separate data and logic a bit.

seed_handler.py

# file that stores the shared seed value 
seed_val_file = "seed_val.txt"

def save_seed(val, filename=seed_val_file):
    """ saves val. Called once in simulation1.py """
    with open(filename, "wb") as f:
        f.write(str(val))

def load_seed(filename=seed_val_file):
    """ loads val. Called by all scripts that need the shared seed value """
    with open(filename, "rb") as f:
        # change datatype accordingly (numpy.random.random() returns a float)
        return int(f.read())

simulation1.py

import random
import seed_handler

def sim1():
    """ creates a new seed and prints a deterministic "random" number """
    new_seed = int("DEADBEEF",16) # Replace with numpy.random.random() or whatever
    print "New seed:", new_seed
    # do the actual seeding of the pseudo-random number generator
    random.seed(new_seed)
    # the result
    print "Random:  ", random.random()
    # save the seed value so other scripts can use it
    seed_handler.save_seed(new_seed)

if __name__ == "__main__":
    sim1()

simulation2.py

import random
import seed_handler

def sim2():
    """ loads the old seed and prints a deterministic "random" number """
    old_seed = seed_handler.load_seed()
    print "Old seed:", old_seed
    # do the actual seeding of the pseudo-random number generator
    random.seed(old_seed)
    # the result
    print "Random:  ", random.random()

if __name__ == "__main__":
    sim2()

Output:

user@box:~/$ python simulation1.py 
New seed: 3735928559
Random:   0.0191336454935

user@box:~/$ python simulation2.py 
Old seed: 3735928559
Random:   0.0191336454935

ADDENDUM

I just read in the comments that this is for research. At the moment, executing simulation1.py overwrites the stored seed value; this might not be desirable. One could add one of these features:

  1. save as json and load to dictionary; that way nothing would get overwritten and every seed value could have notes, a timestamp and a user-generated label associated with it.
  2. simply prompt the user for a yes/no to overwriting the existing value.

Upvotes: 4

davidlatwe
davidlatwe

Reputation: 95

  1. As mentioned by @jDo in comment, renamed globals.py into randGlobal.py.

  2. Added a module testResult.py for testing.


randGlobal.py

import random

def initSeed(seed):
    # declare
    global myRandom
    myRandom = random.Random(seed)

testResult.py

import randGlobal

def randOutput():
    return randGlobal.myRandom.random()

main.py

import randGlobal

# Add a module for testing
import testResult


def test():
    result = testResult.randOutput()
    print result


# main
if __name__ == "__main__":

    seed=10
    randGlobal.initSeed(seed)
    # after init, hava a test
    test()

Upvotes: 1

Related Questions