How to import modules given a list of their names?
Asked Answered
M

6

14

I am trying to import modules from a list. This would be to allow easier editing of imported modules, cleaner error message, and better error handling. Here is basically what I am trying to do:

imports = ['sys', 'itertools', 'datetime', 'os']
for x in imports:
    try:
        import x
        print "Successfully imported ", x, '.'
    except ImportError:
        print "Error importing ", x, '.'

The issue here is that it tries importing x, not the value x should hold. I realize that to import from the list I could do something like below, but I do not see a way to handle the errors with it:

imports = ['sys', 'itertools', 'datetime', 'os']
modules = map(__import__, imports)

Is there a way to integrate the error handling with this method or should I try a different approach?

Morose answered 24/7, 2014 at 17:44 Comment(4)
you have the solution already, in your map you are passing the right function : __import__. Just use __import__(x) in your try blockStettin
"... allow easier editing of imported modules, cleaner error message, and better error handling" - actually, quite the opposite is true. This will prevent any static code analysis tool like PyFlakes from warning you about missing or unused imports, make sorting and editing imports harder, and obfuscate / hide error messages.Finder
Other than testing for optional functionality, import errors either point to a Python installation problem or something that should be caught during testing; in neither case should you bother checking at run time for such errors.Fiddling
Perhaps the print function in the except was a little misleading. The purpose of the error checking is to then install needed modules if they fail on startup.Morose
V
12

Instead of mapping them to ___import__ all at once, just append each module to the list modules one at a time inside the for-loop:

imports = ['sys', 'itertools', 'datetime', 'os']
modules = []
for x in imports:
    try:
        modules.append(__import__(x))
        print "Successfully imported ", x, '.'
    except ImportError:
        print "Error importing ", x, '.'

Note however that most Python programmers prefer the use of importlib.import_module rather than __import__ for this task.


Note too that it might be better to make modules a dictionary instead of a list:

imports = ['sys', 'itertools', 'datetime', 'os']
modules = {}
for x in imports:
    try:
        modules[x] = __import__(x)
        print "Successfully imported ", x, '.'
    except ImportError:
        print "Error importing ", x, '.'

Now, instead of by index:

modules[0].version
modules[3].path

you can access the modules by name:

modules["sys"].version
modules["os"].path
Vaporize answered 24/7, 2014 at 17:48 Comment(3)
This doesn't actually work. The modules aren't recognized when called within the program.Morose
@Morose - The module objects are stored in the list. You need to index it if you want to access them. For example, modules[0].version will be sys.version.Vaporize
@Morose - I used a list because you had one in your post. It might be better though to use a dictionary where the module names are mapped to their objects. See my edit.Vaporize
S
4

None of the most voted options worked for me. They seemed to be imported successfully, but I couldn't use them later. In case you experienced the same issue, this tutorial solved it for me.

modules = ['sys', 'itertools', 'datetime', 'os']  

for lib in modules:
    globals()[lib] = __import__(lib)

PS: I guess they were not added to my global variables before

Sievers answered 4/12, 2020 at 9:34 Comment(0)
L
3

you can import programatically achieving the same effect as import module as module_shortname by using globals():

packages_to_import = [{'name': 'numpy', 'as': 'np'},
                      {'name': 'pandas', 'as': 'pd'}]

for package in packages_to_import:
    package_name = package['name']
    import_as = package.get('as', package_name)

    globals()[import_as] = __import__(package_name)

print(np.version.full_version)
print(pd.__version__)
Lifeless answered 26/5, 2019 at 20:8 Comment(0)
E
1

This worked for me on Python 3.7

modules = ["sys","os","platform","random","time","functools"]

for library in modules:
try:
    exec("import {module}".format(module=library))
except Exception as e:
    print(e)
print(sys.argv)

Importing a submodule:

modules = ["PyQt5"] # pip install PyQt5
submodules = ["QtCore"]

for library in modules:
    for sublibrary in submodules:
        try:
            exec("from {m} import {s}".format(m=library, s=sublibrary))
        except Exception as e:
            print(e)
print(dir()) # Includes QtCore
print(dir(QtCore)) # All functions, classes and variables are exactly correct as with "from PyQt5 import QtCore"

Importing everything:

modules = ["sys","os","platform","random","time","functools"]
for library in modules:
    try:
        exec("from {module} import *".format(module=library))
    except Exception as e:
        print(e)
print(dir()) # Exactly working as thought

Importing a instance or something:

modules = ["PyQt5"] # pip install PyQt5
submodules = ["QtCore"]
func = ["QCoreApplication"]
for library in modules:
    for f in func:
        for sublibrary in submodules:
            try:
                exec("from {m}.{s} import {f}".format(m=library, s=sublibrary, f=f)) 
            except Exception as e:
                print(e)
print(dir()) # Includes QCoreApplication instance

Importing everything from a modules's submodule:

modules = ["PyQt5"] # pip install PyQt5
submodules = ["QtCore"]
for library in modules:
    for sublibrary in submodules:
        try:
            exec("from {m}.{s} import *".format(m=library, s=sublibrary)) # Didn't mention f"" strings all the times. But for beginners .format is better.
        except Exception as e:
            print(e)
print(dir()) # Includes all PyQt5.QtCore stuff
Eadie answered 21/1, 2019 at 5:57 Comment(1)
Using exec() is a security hazard and should generally be avoided. It's also usually unnecessary…Cecum
R
0

You can modify your import x line to use the __import__(x) format

imports = ['sys', 'itertools', 'datetime', 'os','doesntexit']
for x in imports:
    try:
        __import__(x)
        print "Success"
    except ImportError:
        print "Error ", x

Outputs:

Success
Success
Success
Success
Error  doesntexit
Rainmaker answered 24/7, 2014 at 17:53 Comment(1)
You need to somehow save the module object returned by __import__. For example, doing __import__('os');os will raise a NameError unless you do os = __import__('os');os.Vaporize
D
0

Pesky pseudo submodules

This works with pesky pseudo submodules like lxml.etree:

# PyPI imports
import pkg_resources, subprocess, sys

modules   = {'lxml.etree', 'pandas', 'screeninfo'}
required  = {m.split('.')[0] for m in modules}
installed = {pkg.key for pkg in pkg_resources.working_set}
missing   = required - installed

if missing:
    subprocess.check_call([sys.executable, '-m', 'pip', 'install', '--upgrade', 'pip'])
    subprocess.check_call([sys.executable, '-m', 'pip', 'install', *missing])

for module in set.union(required, modules):
    globals()[module] = __import__(module)

Tests:

print(pandas.__version__)
print(lxml.etree.LXML_VERSION)
Disable answered 8/6, 2022 at 1:8 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.