0

Suppose I have two files. In the first file, the main function takes input usr_input and then calls a function myfun in the second file. The functions in the second file imports a module according to usr_input and call its methods. (Of course the imported classes have the same interface)

Currently I am passing usr_input as a parameter and use importlib, as shown in the simplified code:

# A.py
class A:
    def foo(self):
        print('This is class A')

# B.py
class B:
    def foo(self):
        print('This is class B')

# main.py
from test_module.fun import *
if __name__ == '__main__':
    usr_input = 'A' # or 'B'
    myfun(usr_input)

# fun.py
import importlib
def myfun(module_name):
    mn = importlib.import_module('test_module.'+module_name)
    mnc = getattr(mn, module_name)
    mnc().foo()

However importing a module in functions has caused problems and must be replaced (module should be imported before function is called, typically import at the beginning of file). How should I change the design (rather not to import all possible classes: A, B...)?

PS: reading the module name from saved external file does not work because myfun is initialized before value of it is known.

  • 1
    Why not create 2 separate methods for 'A' and for 'B' and just use whichever method matches the `usr_input` instead of importing based on the input? – Alan Kavanagh Feb 07 '18 at 17:28
  • @AK47 what do you mean by "create 2 separate methods for 'A' and for 'B"? Will that produce duplicated code? –  Feb 07 '18 at 17:32

2 Answers2

0

Dynamic loading of modules:

>>> moduleNames = ['sys', 'os', 're', 'unittest'] 
>>> moduleNames
['sys', 'os', 're', 'unittest']
>>> modules = map(__import__, moduleNames)

Dynamic module import in Python

Update in response to OP comment:

If you don't want to use the builtin python library for dynamically importing modules, then you're not going to be able to dynamically import modules, unless you want to write your own library duplicating its behavior.

Post the error/issue with importlib or just statically import your libraries and route your thread via if statements.

John R
  • 1,505
  • 10
  • 18
  • Sorry, but I do not see how this solves my case, I am already using `importlib`. –  Feb 07 '18 at 17:35
  • Thanks, it does seem impossible to achieve something like this. –  Feb 07 '18 at 17:45
0

If you're not trying to import completely arbitrary modules and just need to pick from a list, you can just use an if-else block (or another similar construct). This is often done to work around imports that are different in Python 2.7 vs 3.x, for example.

Here's a simple way to pick between two imports:

def myfun(module_name):
    if module_name == 'A':
        import module_a as module
    else:
        import module_b as module
    module.foo()
sam
  • 366
  • 1
  • 11
  • Sorry, but this is essentially the same as my code, importing a module in this function will cause problems as I stated. I handled module name checking in the main function, so 'arbitrary module name' is not really a problem. –  Feb 07 '18 at 17:36