0

I want to import modules dynamically in my class depending on some conditions.

    class Test(object):
        def __init__ (self,condition):
            if condition:
                import module1 as mymodule
            else:
                import module2 as mymodule

            self.mymodule = mymodule

        def doTest(self):
            self.mymodule.doMyTest

where module1 and module2 implement doMyTest in different way.

Calling it as

    mytest1 = Test(true)  # Use module1
    mytest2.doTest()

    mytest2 = Test(false)  # Use module2
    mytest2.doTest()

This works but is there possibly a more idiomatic way? Are there any possible problems?

5
  • Actually, this doesn't really work quite as well as you think it does… but that's about what the import statements do globally and locally, and has nothing to do with the condition stuff. Commented Aug 20, 2013 at 19:56
  • there might be a more idiomatic way depending on the actual nature of the condition you're checking. What problem are you trying to solve? Commented Aug 20, 2013 at 19:57
  • I am trying to develop a test suite where the actual implementation of the test methods may differ, depending in which category tested object falls. Commented Aug 20, 2013 at 21:17
  • @abarnert can you please give more info or point to some resources, why this construction possesses a problem? Commented Aug 20, 2013 at 21:32
  • @peterk: It's not really a problem, so much as possibly non-obvious behavior. The import table is global. So, module1 will only be executed the first time you import module1 as mymodule; after that, each subsequent import module1 as mymodule is effectively equivalent to mymodule = sys.modules['module1']. So, it might be less misleading to make that explicit: import module1 and module2 once, then just have if…: self.mymodule = module1… else: self.mymodule = module2. Commented Aug 20, 2013 at 21:55

1 Answer 1

1

Of course normally you don't want to import modules in the middle of an __init__ method, but a testing class is an obvious exception to that rule, so let's ignore that part and imagine you were doing this at top level:

if test_c_implementation:
    import c_mymodule as mymodule
else:
    import py_mymodule as mymodule

That's perfectly idiomatic. In fact, you see code like that in the stdlib and other code written by core developers.

Except in the very-common EAFP cases, where the condition is just there to avoid an exception, in which case it's more idiomatic to just do this:

try:
    import lxml.etree as ET
except ImportError:
    import xml.etree.cElementTree as ET
Sign up to request clarification or add additional context in comments.

3 Comments

Thank you. In my case the import can be placed in other Test method, not init. I am more interested whether passing the module reference as a Test attribute is a valid Python technique.
@peterk: It wasn't so much about the __init__ as about doing it in any method. And the point is: that's an odd thing to do; the only obvious use for that is in a test library… which is exactly what you're writing, so it doesn't matter that it's odd.
@peterk: Anyway, a module is a first-class value, just a namespace like any other, so it's certainly valid to pass one around, store it as an attribute, etc. Most modules aren't really designed to be thought of as values, but there are definitely reasonable exceptions (even in the stdlib, random has the exact same API as a random.Random instance), and again, it may easily be reasonable for a test library to think of a module as a value even if normal users of the module wouldn't.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.