0

This is my not working code (simplified):

File A.py:

from B import *

class A(object):
    def __init__(self):
        A.instance = self
        self.b = B()

    def testA(self):
        print "success"

if __name__ == '__main__':
    a = A()
    a.b.testB()

File B.py:

from A import *

class B(object):
    def testB(self):
        A.instance.testA()

It fails at the last line of B.py: type object 'A' hast no attribute 'instance'. It works if A and B are in the same file. How can I split this into multiple files to prevent having my entire project in one giant file?

Toast
  • 596
  • 2
  • 19
  • 39
  • Until you run `A.__init__`, `A.instance` is undefined. What are you actually trying to achieve?! – jonrsharpe Aug 16 '14 at 20:11
  • 1
    @jonrsharpe: A.__init__ is run, because he does `a = A()`. But it's not the right A, because the module is imported twice. – BrenBarn Aug 16 '14 at 20:13

1 Answers1

1

When you run A.py, it is considered to have the name __main__ (as used in your if __name__ == '__main__' test). But when B imports A, it has the name A. So the module is loaded twice under different names, and two copies of it exist. When your "main" block runs, it is instantiating the A class from __main__, but B.py only sees the A class from the module A. (See this recent question for a similar issue, and this one for some more description of the double-import problem.)

The solution is to separate out the code you need to import from the file you want to run as a script. Put the classes in separate files A.py and B.py, then have a third file (script.py or whatever) that does whatever it needs to with both files. For instance, your script.py could do:

from A import A

if __name__ == "__main__":
    a = A()
    a.b.testB()

You can then set up A and B like this:

### A.py
import B

class A(object):
    def __init__(self):
        A.instance = self
        self.b = B.B()

    def testA(self):
        print "success"

### B.py
import A

class B(object):
    def testB(self):
        A.A.instance.testA()

Having multiple modules that import each other is in general a risky proposition. If you have multiple classes that need to reference one another, the easiest thing is to keep them in the same module. (If this becomes awkward because you have large numbers of mutually referential classes, you might want to revist your overall design, since large numbers of mutually referential classes can be awkward.)

Community
  • 1
  • 1
BrenBarn
  • 242,874
  • 37
  • 412
  • 384
  • I'm getting a "Global name 'A' is not defined in file B." – Toast Aug 16 '14 at 20:18
  • @Toast: What do you have in A and B? You still need the imports in both files. – BrenBarn Aug 16 '14 at 20:19
  • @Toast: As I said, you need the imports *in both files*. You still need `from A import *` (or `from A import A`) in B.py, just like you had at first. – BrenBarn Aug 16 '14 at 20:23
  • I updated the question again. It fails when importing in B in line 1: "ImportError: cannot import name A", or with an asterisk: "global name 'A' is not defined" – Toast Aug 16 '14 at 20:28
  • @Toast: Oh whoops, forgot about that complication. You will need to change the form of your imports. See my edited answer. – BrenBarn Aug 16 '14 at 20:30