Hello,

I have a structure like this:

package/
	__init__.py

	subpackage1/
		__init__.py
		baseclass.py

		subpackageA/
			__init__.py
			ClassA.py

		subpackageB/
			__init__.py
			ClassB.py

in package/__init__.py and package/subpackage1/__init__.py I am importing the subpackages so that in my app I can just call
import package
instead of having to import each subpackage individually

Here is package/subpackage1/__init__.py for example

from baseclass import BaseClass
import subpackageA
import subpackageB

I run into a problem where in classA or classB I create a class that tries to inherit from BaseClass, which is of located higher in the hierarchy.

class ClassA(package.subpackage1.BaseClass):
    pass

It gives me
exceptions.AttributesError: 'module' object has no attribute 'subpackage1'


Although I see no reason why subpackage1 wouldn't be defined yet, BaseClass is even imported before it tries to import subpackageA, I'm guessing this is still some sort of circular reference thing though.

This seems like something that would be a common thing to want to do. Any help would be appreciated, thanks!

Recommended Answers

All 5 Replies

What does your main package __init__ file look like? It could be that you're doing something like from subpackage1 import * , in which case, the module subpackage1 wouldn't actually be defined. You'd just be dumping everything from its namespace into the main one. Of course, this is just my guess at what's going on in your package/__init__.py file.

Also, you could always use the sys module and inside the ClassA.py, do something like:

import sys
sys.path.append("..")  # look inside parent directory (subpackage1/)
from baseclass import BaseClass  # it will now find this in the parent dir

class ClassA(BaseClass):
    pass

Thank you for the reply.

No, I just have import package1 in there. I couldn't get your alternative code to work quickly, however, relative imports do work, so if I put in package/subpackage1/subpackageA/ClassA.py
from ..baseclass import BaseClass

Well, it works but I'd prefer to just be able to put
import package
(Which I should note, is what I was doing before, my code above didn't have that line)


One thing I should note, the error is not occuring on the line where I import, it is occuring on the line where I define the class, this is even the case if I try to import package.subpackage1 directly, like so:

import package.subpackage1

class ClassA(package.subpackage1.BaseClass):
    pass

The error does NOT occur on the line where it imports, it occurs on the line where the class is defined. Yet it still refers to package1 being missing.

If I take out the actual inheritance but leave in import package the code runs without error.

As I interpret your package structure, your import should go something like this:

from package.subpackage1.baseclass import BaseClass

class ClassA(BaseClass):
    pass

Hmm, that seems to work.

I'm guessing its just because I'm pulling that class out of the module directly, so its not looping through all the inits again, or something along those lines.

I was hoping to organize my package in such a way to just use import package everywhere, even within my package but I guess that's asking too much. Too many possibilities of traps like this.

I'll use one of the solutions you two ahve given me, but purely out of curiosity, I tried this and I get the old error:

import package.subpackage1.baseclass

class ClassA(package.subpackage1.baseclass.BaseClass):
    pass

I'm surprised this doesn't work and the from/import does. Does using import initialize the whole hierarchy again and from does not?

purely out of curiosity, I tried this and I get the old error:

import package.subpackage1.baseclass

class ClassA(package.subpackage1.baseclass.BaseClass):
    pass

My only question to you is, why would you want to do it in that way? I think it's easier to understand the following when reading through a piece of code:

from package.subpackage1.baseclass import BaseClass
class ClassA(BaseClass):
    pass

That seems to be the most straight forward method to get BaseClass into your code and would be easiest for someone debugging to follow. A quick search for BaseClass would lead them to the import statement instead of staring at package.subpackage1.baseclass and thinking it was some type of sub-class method or sub-sub-class that was initialized somewhere.

I've always liked Guido's philosophy that says code is read much more than it is written, so you should aim for high readability and easy traceability in your code. Hiding imports away in packages and using overly-complicated import methods seems to be very unpythonic. At least in my opinion.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.