2

I have a module named dynamic_cls_ex.py and two classes named FooButton and BarButton. I am using the below code to dynamically instantiate the class I am interested in from a string.

The problem: I'm using __import__ to import the module, which causes main to run twice. this is my elementary understanding. Please feel free to give me a better explanation on what's actually going on

# !/usr/bin/python

class FooButton(object):
    def __init__(self):
        print 'I am a foo button'

class BarButton(object):
    def __init__(self):
        print 'I am a bar button'


method = 'Foo'
class_name = '%sButton' % method
module = __import__('dynamic_cls_ex')
Button = getattr(module, class_name)
Button()


# OUTPUT:
# >> I am a foo button
# >> I am a foo button

How can I dynamically instantiate a class without needing to import the module I'm currently running?

Jess
  • 3,097
  • 2
  • 16
  • 42

3 Answers3

3

Well, you haven't specified what's in dynamic_cls_ex.py, but I assume it has some top-level code that actually runs (which is what you're calling the main function, I think).

This code is run whenever its enclosing python file is itself run at the top level of the interpreter, or when it is imported (with __import__ you're explicitly circumventing the check to not reload already-present modules).

But you can force code to be only run when it is actually run at the top level by checking for __main__ -- "this module represents the (otherwise anonymous) scope in which the interpreter’s main program executes". So if you wrap the top-level code in if __name__ == "__main__": it will only run from the main program, and not when imported.

See also What does if __name__ == "__main__": do? here on SO.

Community
  • 1
  • 1
Andrew Jaffe
  • 26,554
  • 4
  • 50
  • 59
0

Adding a guard for if __name__ == '__main__' and placing the code that was in the global scope prevented the code from running twice.

When I run the below code:

print __name__
module = __import__('dynamic_cls_ex')

# I get:
# >> __main__
# >> dynamic_cls_ex

So I changed the code to have a guard like the above snippet, I got the following output, which demonstrates why the guard worked, and that I didn't get any more duplicates.

# placed below FooButton BarButton class definitions

print __name__

if __name__ == '__main__':
    method = 'Foo'
    class_name = '%sButton' % method
    module = __import__('dynamic_cls_ex')
    Button = getattr(module, class_name)
    Button()

# Output:
# >> __main__
# >> dynamic_cls_ex
# >> I am a foo button
Jess
  • 3,097
  • 2
  • 16
  • 42
-1

You can use globals() function to get a dictionary with global name bindings. Then you can access this dictionary to get your class.

kraskevich
  • 18,368
  • 4
  • 33
  • 45