Snowman
Snowman

Reputation: 32071

Importing a module in Python from a string

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

Answers (5)

Nihathrael
Nihathrael

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

BrenBarn
BrenBarn

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

Jon Gauthier
Jon Gauthier

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

David Z
David Z

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

btel
btel

Reputation: 5693

How about:

module = __import__('MSObject.' + 'MBSquareObject')

Upvotes: 0

Related Questions