ThunderEX
ThunderEX

Reputation: 703

How to selectively import module in python?

I have several different modules, and I need to import one of them depending on different situations, for example:

if check_situation() == 1:
    import helper_1 as helper
elif check_situation() == 2:
    import helper_2 as helper
elif ...
    ...
else:
    import helper_0 as helper

these helpers contain same dictionaries dict01, dict02, dict03...but have different values to be called in different situations.

But this has some problems:

  1. import sentences are all written in the top of a file, but check_situation() function here needs prerequisites so that it's now far from top.
  2. more than 1 file needs this helper module, so it's hard and ugly to use this kind of import.

So, how to re-arrange these helpers?

Upvotes: 9

Views: 5336

Answers (4)

I agree that the approaches given in the other answers are closer to the main question posed in your title, but if the overhead on importing modules is low (as importing a couple of dictionaries likely is) and there are no side-effects to importing, in this case, you may be better off importing them all and selecting the proper dictionary later in the modules:

import helper_0
import helper_1
...
helperList = [helper_0, helper_1, helper_2...]
...
helper = helperList[check_situation()]

Upvotes: 1

ThunderEX
ThunderEX

Reputation: 703

Solve it myself, refered to @Michael Scott Cuthbert

# re_direct.py

import this_module
import that_module

wanted = None


# caller.py
import re-direct

'''
many prerequisites
'''
def imp_now(case):
    import re_direct
    if case1:
        re_direct.wanted = re_direct.this_module
    elif case2:
        re_direct.wanted = re_direct.that_module

then, if in caller, I call that imp_now, then wanted, no matter called in caller file or other file calling this wanted, will all be re-directed to this_or_that_module.

also, for I import re_direct only in a function, so you will not see this module anywhere else, but only see wanted.

Upvotes: 1

Ashwini Chaudhary
Ashwini Chaudhary

Reputation: 250951

You can use __import__(), it accepts a string and returns that module:

helper=__import__("helper_{0}".format(check_situation()))

example :

In [10]: mod=__import__("{0}math".format(raw_input("enter 'c' or '': ")))
enter 'c' or '': c             #imports cmath

In [11]: mod.__file__
Out[11]: '/usr/local/lib/python2.7/lib-dynload/cmath.so'

In [12]: mod=__import__("{0}math".format(raw_input("enter 'c' or '': ")))
enter 'c' or '': 

In [13]: mod.__file__
Out[13]: '/usr/local/lib/python2.7/lib-dynload/math.so'

As pointed out by @wim and from python3.x docs on __import__():

Import a module. Because this function is meant for use by the Python interpreter and not for general use it is better to use importlib.import_module() to programmatically import a module.

Upvotes: 5

wim
wim

Reputation: 362707

Firstly, there is no strict requirement that import statements need to be at the top of a file, it is more a style guide thing.

Now, importlib and a dict can be used to replace your if/elif chain:

import importlib

d = {1: 'helper_1', 2: 'helper_2'}
helper = importlib.import_module(d.get(check_situation(), 'helper_0'))

But it's just syntactic sugar really, I suspect you have bigger fish to fry. It sounds like you need to reconsider your data structures, and redesign code.

Anytime you have variables named like dict01, dict02, dict03 it is a sure sign that you need to gear up a level, and have some container of dicts e.g. a list of them. Same goes for your 'helper' module names ending with digits.

Upvotes: 5

Related Questions