How to share variables across scripts in python?

Viewed 78767

The following does not work

one.py

import shared
shared.value = 'Hello'
raw_input('A cheap way to keep process alive..')

two.py

import shared
print shared.value

run on two command lines as:

>>python one.py
>>python two.py

(the second one gets an attribute error, rightly so).

Is there a way to accomplish this, that is, share a variable between two scripts?

14 Answers

Share a dynamic variable by Redis:

script_one.py

from redis import Redis
from time import sleep

cli = Redis('localhost')
shared_var = 1

while True:
   cli.set('share_place', shared_var)
   shared_var += 1
   sleep(1)

Run script_one in a terminal (a process):

$ python script_one.py

script_two.py

from redis import Redis
from time import sleep

cli = Redis('localhost')

while True:
    print(int(cli.get('share_place')))
    sleep(1)

Run script_two in another terminal (another process):

$ python script_two.py

Out:

1
2
3
4
5
...

Dependencies:

$ pip install redis
$ apt-get install redis-server

If you wanna read and modify shared data between 2 scripts which run separately, a good solution would be to take advantage of python multiprocessing module and use a Pipe() or a Queue() (see differences here). This way you get to sync scripts and avoid problems regarding concurrency and global variables (like what happens if both scripts wanna modify a variable at the same time).

The best part about using pipes/queues is that you can pass python objects through them.

Also there are methods to avoid waiting for data if there hasn't been passed yet (queue.empty() and pipeConn.poll()).

See an example using Queue() below:

    # main.py
    from multiprocessing import Process, Queue
    from stage1 import Stage1
    from stage2 import Stage2


    s1= Stage1()
    s2= Stage2()

    # S1 to S2 communication
    queueS1 = Queue()  # s1.stage1() writes to queueS1

    # S2 to S1 communication
    queueS2 = Queue()  # s2.stage2() writes to queueS2

    # start s2 as another process
    s2 = Process(target=s2.stage2, args=(queueS1, queueS2))
    s2.daemon = True
    s2.start()     # Launch the stage2 process

    s1.stage1(queueS1, queueS2) # start sending stuff from s1 to s2 
    s2.join() # wait till s2 daemon finishes
    # stage1.py
    import time
    import random

    class Stage1:

      def stage1(self, queueS1, queueS2):
        print("stage1")
        lala = []
        lis = [1, 2, 3, 4, 5]
        for i in range(len(lis)):
          # to avoid unnecessary waiting
          if not queueS2.empty():
            msg = queueS2.get()    # get msg from s2
            print("! ! ! stage1 RECEIVED from s2:", msg)
            lala = [6, 7, 8] # now that a msg was received, further msgs will be different
          time.sleep(1) # work
          random.shuffle(lis)
          queueS1.put(lis + lala)             
        queueS1.put('s1 is DONE')
    # stage2.py
    import time

    class Stage2:

      def stage2(self, queueS1, queueS2):
        print("stage2")
        while True:
            msg = queueS1.get()    # wait till there is a msg from s1
            print("- - - stage2 RECEIVED from s1:", msg)
            if msg == 's1 is DONE ':
                break # ends loop
            time.sleep(1) # work
            queueS2.put("update lists")             

EDIT: just found that you can use queue.get(False) to avoid blockage when receiving data. This way there's no need to check first if the queue is empty. This is no possible if you use pipes.

This method seems straight forward for me:

class SharedClass:

def __init__(self):
    self.data = {}

def set_data(self, name, value):
    self.data[name] = value

def get_data(self, name):
    try:
        return self.data[name]
    except:
        return "none"

def reset_data(self):
    self.data = {}

sharedClass = SharedClass()

PS : you can set the data with a parameter name and a value for it, and to access the value you can use the get_data method, below is the example:

to set the data

example 1:
sharedClass.set_data("name","Jon Snow")
example 2:
sharedClass.set_data("email","jon@got.com")\

to get the data

sharedClass.get_data("email")\

to reset the entire state simply use

sharedClass.reset_data()

Its kind of accessing data from a json object (dict in this case)

Hope this helps....

You could use the basic from and import functions in python to import the variable into two.py. For example:

from filename import variable

That should import the variable from the file. (Of course you should replace filename with one.py, and replace variable with the variable you want to share to two.py.)

You can also solve this problem by making the variable as global

python first.py

class Temp:
    def __init__(self):
        self.first = None

global var1
var1 = Temp()
var1.first = 1
print(var1.first)

python second.py

import first as One
print(One.var1.first)
Related