Accessing and updating global variables among several modules

Fuming Wang fumingw at tom.com
Thu Jul 17 08:28:49 EDT 2003


bokr at oz.net (Bengt Richter) wrote in message news:<bepqje$8cm$0 at 216.39.172.122>...
> On 11 Jul 2003 20:38:48 -0700, fumingw at tom.com (Fuming Wang) wrote:
> 
> >Hi,
> >
> >I have several modules that need to access global variables among
> >them.  I can do that by import modules:
> >
> >module A:
> >gA = 'old'
> >
> >module B:
> >import A
> >print A.gA
> >>>> 'old'
> >
> >change gA in module A after some initialization:
> >def init_fuct():
>   global gA   # w/o this line, gA is just a local variable, and init_fuct() is well named ;-)
> >    gA = 'new'
> >
> (I assume the above function was in module A, and either invoked from there or as A.init_fuct()
> from somwhere else).
> 
> >no change in module B:
> >print A.gA
> >>>> 'old'
>  With the code above, there was no change in A either ;-)
> >
> >However, when I modify these global variables in one module, the other
> >modules would not see the changes.  Any one has any suggestions? ( I
> >don't want to use from A import *)
> >
> Just make sure you actually change A.gA and you should be able to see the change from B as A.gA.
> Unless I am missing something.
> 
> Regards,
> Bengt Richter


Hi,

Thanks for the replies.  I have actually found a solution to the
problem. The problem is caused by Python creating two copies of the
module that is passed to the interpreter. Here is a short report of
what the problem is and how to avoid it.  Hope this can be of help for
others.

Fuming

P.S. I am running Python 2.3 b2 on Windows2000

********************************************

It started out as a simple desire to have communications between two
modules that import each other (circular imports).  It turns out to be
quite a gotcha,which I thick could catch many experience Python user
by surprise.  You can now avoid this pitfall and gain some insights in
how module imports are handles.
So here it goes.


------ File A.py ----------

    import B

    a = object()

    def printa():
        print 'a from A:', a

    def printb():
        print 'b from A:', B.b 

    if __name__ == '__main__':
        printa()
        printb()
        B.printa()
        B.printb()


------ File B.py ----------


    import A

    b = object()

    def printa():
        print 'a from B:', A.a

    def printb():
        print 'b from B:', b


Run it from Python interpretor
>python A.py

    a from A: <object object at 0x007DD3C8>
    b from A: <object object at 0x007DD3C0>
    a from B: <object object at 0x007DD3B8>
    b from B: <object object at 0x007DD3C0>


If you look at the addresses of the printed objects carefully, you
will find that the same object b in module B can be seen by both
modules (0x..3C0), while object a seems to be totally different
objects seeing from module A and B (0x..3C8, 0x..3B8).

Why are module A and B are seeing different objects from the same
object a? We will find out after the following experiment.  Let's add
the following two lines to file A.py and B.py seperately:

    print 'init module A:', a, __name__

    print 'init module B:', b, __name__

This line will tell us when each module is
created/initialized/loaded/imported. Let's run the script once again.
We will have the following results.

    init module A: <object object at 0x007DD3B8> A
    init module B: <object object at 0x007DD3C0> B
    init module A: <object object at 0x007DD3C8> __main__
    a from A: <object object at 0x007DD3C8>
    b from A: <object object at 0x007DD3C0>
    a from B: <object object at 0x007DD3B8>
    b from B: <object object at 0x007DD3C0>

Haaa!  There are two copies on module A.  One is called 'A', the other
is
called '__main__'.  Functions in module A is seeing module __main__.a
(0x..3C8),while functions in module B is seeing module A.a (0x..3B8). 
No wonder they are seeing two different object.  Knowing the cause of
this problem, we can devise many solutions. Some are more proper than
others.

Let's discuss the proper one first.  The only reason module A is
created twice is because it is invoked by the interpreter. We only
need to write another short module C as following, and the problem is
solved.


--------- file C.py ----------------

    import A
    import B

    if __name__ == '__main__':
        A.printa()
        A.printb()
        B.printa()
        B.printb()


Improper solutions including:

change in A.py

    if __name__ == '__main__': ----> if __name__ == 'A':

or change in B.py

    import A  ---->  import sys; import sys.modules['__main__']




More information about the Python-list mailing list