Python 3.5 "importerror: Cannot Import Name 'somename'
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'"