0

I have 2 python scripts. I am trying to access value of global variable from one.py into two.py.

Here is my code.

one.py

import two

myvar = False

def fun():
    global myvar
    myvar = True

two.use_me()

two.py

import one
print "from two: ", one.myvar
def use_me():
    print "This is used in one.py"

I am getting this error:

$ python two.py
from two: 
Traceback (most recent call last):
  File "two.py", line 1, in <module>
    import one
  File "one.py", line 1, in <module>
    import two
  File "two.py", line 2, in <module>
    print "from two: ", one.myvar
AttributeError: 'module' object has no attribute 'myvar'

Not sure what I am missing here. Can someone please help?

Dunes
  • 37,291
  • 7
  • 81
  • 97
npatel
  • 1,081
  • 2
  • 13
  • 21

1 Answers1

4

You have a circular input. When you run two.py it executes import one which then executes import two. Now the import one returns immediately, the module object was already created, but it is empty! so on the next line you get an AttributeError.

That's what the traceback is telling you:

  • while running two.py's statement import one
  • while running one.py's statement import two
  • in file two.py I got an AttributeError executing print "two.py", one.myvar

Your one.py module does not need two at all so you should remove the import two statement.

Circular imports are generally a very strong sign that something is wrong in your design/architecture. Try to move functions/classes/variables around to avoid them, eventually combining the two modules.

There are ways to make them work but they are brittle and should be avoided.


If you have a function in two.py which needs stuff from one.py you should really move the function into one.py.

Yuo can also consider creating a three.py that imports both two.py and one.py.

How exactly you can break your circular import depends on the exact code you have so with just toy example we can continue for days in saying "you can just remove this" or "you can just move that". If you want a more precise answer we'd need to see very precise code that represents the definitions involved in the two modules.

Bakuriu
  • 98,325
  • 22
  • 197
  • 231
  • edited code to clear one point that I do need to `import two` as `one.py` uses couple of functions from `two.py` – npatel Oct 04 '18 at 19:48
  • That is sort of true. `import one` doesn't return immediately. It imports two which skips the import one statement since one is already imported. It then continues to execute all of two. Since at the point in one where import two is excuted, myvar doesnt exist, it throws this error. I dont recommend this, but moving the import line to the bottom of one.py "fixes" this error. – Mateo Oct 04 '18 at 19:49
  • 1
    @npatel I believe you should simply not have that design. There are many ways to break circular dependencies but they depend on the exact code. Right now I'd say: just remove the `print "two.py", one.myvar`. Do the functions defined in `two` that you need in `one` depend on `one` and also on things defined in `two`? If not: just move them into `one`! – Bakuriu Oct 04 '18 at 19:53
  • @Mateo I don't see how the description I give is different than that. The import is not "skipped" it *succeeds* because the module object is created immediately and immediately inserted into `sys.modules`. When I say `import one` returns immediately I mean that it returns the value it finds in `sys.modules` without re-executing `one.py` (and ending up in an infinite loop) – Bakuriu Oct 04 '18 at 19:55
  • @npatel To be clear: if you can just move `use_me` into `one.py` you fixed your problem. If `use_me` uses `two.f` just move `f` into `one.py`. If `f` uses `g` just move `g` too into `one.py`. Keep doing this until you either end up with `two.py` not needing `one.py` anymore, or `two.py` completely empty. – Bakuriu Oct 04 '18 at 20:03