Reputation: 32071
I have a string type
with a value of "MBSquareObject". MBSquareObject
is class in a file called MBObject
. I want to import MBSquareObject
dynamically.
If the square object was in a file of its own, this works:
__import__(type)
However, what I want to do is the equivalent of from MBObject import MBSquareObject
. However, this doesn't work:
from MBObject __import__(type)
How else could I do this?
Edit: the answers given are assuming that MBSquareObject is some sort of object on MBObject, but it's just another class. MBSquareObject is a subclass of MBObject, so they are listed in the same file.
Edit: for some reason none of the answers are working. Here's what I have:
# this is imported at the top of the file
from MBObject import MBObject
type = 'MBSquareObject'
__import__('MBObject', globals(), locals(), [type])
object_class = eval(type)
object = object_class()
Error: NameError: name 'MBSquareObject' is not defined
Upvotes: 2
Views: 1643
Reputation: 515
Try this:
module = __import__('MSObject', globals(), locals(), ['MBSquareObject'], -1)
Plugged together using the examples found here:
http://docs.python.org/2/library/functions.html#import
Upvotes: 1
Reputation: 251378
Your example indicates that the module name MBObject
doesn't need to be accessed dynamically, only the object inside. In that case, you can just do
import MBObject
thing = getattr(MBObject, type)
Edit: One problem is that you are giving your module and class the same name, which makes it difficult to distinguish them in your code. You're getting confused between classes and modules. You have two things called MBObject. One is a module, the other is a class inside that module. When you do from MBObject import MBObject
, you import the class, but give yourself no reference to the module, making it awkward to subsequently import a second class (MBSquartObject) from the same module.
You can get the effect you want by using the code I gave above, but you must not do from MBObject import MBObject
--- when you do that, you don't give yourself a reference to the module, only the class in that module. Instead, just do import MBObject
and then access the MBObject class via MBObject.MBObject
.
If you want to be able to refer to both the MBObject class and other classes from the same module without prefixing them with the module name, give the module a different name. Python style guidelines advise naming modules in all lowercase and classes in MixedCase. So name your module mbobject.py. Then you can do:
import mbobject
from mbobject import MBObject
thing = getattr(mbobject, type)
In general it is not a good idea in Python to give the same name to a module and a class. Modules and classes are different things, and giving them the same name can lead to confusions like this where you're not clear on whether you're dealing with the module or the class.
Upvotes: 4
Reputation: 25582
__import__
can take additional arguments specifying exactly which objects should be imported. From the return of this function you can fetch whatever object you desire.
source_module = 'MBObject'
object_in_module = 'MBSquareObject'
obj = getattr(__import__(source_module, globals(), locals(), [object_in_module]),
object_in_module)
Upvotes: 3
Reputation: 131600
The full syntax of the __import__
function is described in the documentation:
__import__(name[, globals[, locals[, fromlist[, level]]]])
Here fromlist
is the list of items to import from the imported module. A statement like
from module import object1, object2
is implemented as something like
module = __import__('module', globals(), locals(), ['object1', 'object2'])
object1 = getattr(module, 'object1')
object2 = getattr(module, 'object2')
So in your case, you could use
module = __import__('MBObject', globals(), locals(), [type])
the_object = getattr(module, type)
In recent versions of Python, since 3.1, there is a module importlib
which you can presumably use to do this. Though the only way I can find to do so is to use the module's implementation of __import__
, which is basically the same as the built-in implementation, so I guess you might as well use the built-in one.
Upvotes: 1