Skip to content Skip to sidebar Skip to footer

Python 3.5 "importerror: Cannot Import Name 'somename'

I am trying to implement a small library for Python 3.5 but keep struggling with how to correctly handle the structuring of the packages/modules and how to get the imports to work.

Solution 1:

Your issue is caused by a circular import. The baseclass module is trying to import SubClass1 from the subclass1 module, but subclass is trying to import BaseClass right back. You get NameError because the classes haven't been defined yet when the import statements are running.

There are a few ways to solve the issue.

One option would be to change your style of import. Instead of importing the classes by name, just import the modules and look up the names as attributes later on.

from . import baseclassclass SubClass1(baseclass.BaseClass):
    pass

And:

from . import subclass1

classBaseClass:
    defmake(self,somearg):
        # ...
        ret = subclass1.SubClass1()

Because SubClass1 needs to be able to use BaseClass immediately at definition time, this code may still fail if the baseclass module is imported before subclass1. So it's not ideal

Another option would be to change baseclass to do its import below the definition of BaseClass. This way the subclass module will be able to import the name when it needs to:

classBaseClass:
    defmake(self,somearg):
        # .. some logic to decide which subclass to create
        ret = SubClass1()

from .subclass1 import SubClass1

This is not ideal because the normal place to put imports is at the top of the file. Putting them elsewhere makes the code more confusing. You may want to put a comment up at the top of the file explaining why you're delaying the import if you go this route.

Another option may be to combine your two modules into a single file. Python doesn't require each class to have its own module like some other languages do. When you have tightly coupled classes (like the ones in your example), it makes a lot of sense to put them all in one place. This lets you avoid the whole issue, since you don't need any imports at all.

Finally, there are some more complicated solutions, like dependency injection. Rather than the base class needing to know about the subclasses, each subclass could register itself by calling some function and passing a reference to itself. For example:

# no imports of subclasses!defBaseClass:
    subclasses = []

    defmake(self, somearg):
        for sub in self.subclasses:
            if sub.accepts(somearg):
                return sub()
        raise ValueError("no subclass accepts value {!r}".format(somearg))

    @classmethoddefregister(cls, sub):
        cls.subclasses.append(sub)
        return sub        # return the class so it can be used as a decorator!

And in subclass.py

from .baseclassimport BaseClass

@BaseClass.registerclassSubClass1(BaseClass):
    @classmethoddefaccepts(cls, somearg):
        # put logic for picking this subclass here!returnTrue

This style of programming is a bit more complicated, but it can be nice since it's easier to extend than a version where BaseClass needs to know about all of the subclasses up front. There are a variety of ways you can implement this style of code, using a register function is just one of them. One nice thing about it is that it doesn't strictly require inheritance (so you could register a class that doesn't actually inherit from BaseClass if you wanted to). If you are only dealing with actual inheriting subclasses, you might want to consider using a metaclass that does all the registration of subclasses for you automatically.

Post a Comment for "Python 3.5 "importerror: Cannot Import Name 'somename'"