Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

how to import a submodule in Python (without `exec`)

I would like to import a submodule without knowing its name beforehand,

>>> __import__("os.path")
<module 'os' from '/usr/lib/python3.3/os.py'>

Doesn't work as you might expect, returning os, not os.path.

I came up with this solution.

def import_submodule(mod, submod):
    ns = {}
    exec_str = "from %s import %s as submod" % (mod, submod)
    exec(exec_str, ns, ns)
    return ns["submod"]

This gives the result:

>>> import_submodule("os", "path")
<module 'posixpath' from '/usr/lib/python3.3/posixpath.py'>

However I would rather not use exec() because its rather bad practice and seems unnecessary when Pythons import mechanisms are available already through __import__, imp and importlib modules.

Is there a way in Python3.x to do this kind of import though a function call, rather then using exec() ?

like image 605
ideasman42 Avatar asked Sep 27 '13 06:09

ideasman42


People also ask

What does __ import __ do in Python?

The __import__() in python module helps in getting the code present in another module by either importing the function or code or file using the import in python method. The import in python returns the object or module that we specified while using the import module.

What are the different methods of importing the Python module?

So there's four different ways to import: Import the whole module using its original name: pycon import random. Import specific things from the module: pycon from random import choice, randint. Import the whole module and rename it, usually using a shorter variable name: pycon import pandas as pd.


2 Answers

Use importlib.import_module:

>>> import importlib
>>> importlib.import_module('os.path')
<module 'posixpath' from '/usr/lib/python2.7/posixpath.pyc'>

This should work in python2.7+ and 3.1+.

like image 73
Bakuriu Avatar answered Sep 30 '22 04:09

Bakuriu


Note that if you want do: from A import B as C as a function call, importlib.import_module won't always work, since B may not be a module.

Heres a function which uses importlib and getattr.

def my_import_from(mod_name, var_name):
    import importlib
    mod = importlib.import_module(mod_name)
    var = getattr(mod, var_name)
    return var

So this:

from os.path import dirname as var

Can be replaced with this:

var = my_import_from("os.path", "dirname")

Which avoids exec and allows both submodules and any variables defined in the module.

Since my question explicitly says importing a submodule, the answer from @Bakuriu is correct, however including this for completeness and it may help others who run into the same problem.

like image 45
ideasman42 Avatar answered Sep 30 '22 04:09

ideasman42