How to make global imports from a function?

PythonImportModulePython Module

Python Problem Overview


I fear that this is a messy way to approach the problem but...

let's say that I want to make some imports in Python based on some conditions.

For this reason I want to write a function:

def conditional_import_modules(test):
    if test == 'foo':
        import onemodule, anothermodule
    elif test == 'bar':
        import thirdmodule, and_another_module
    else:
        import all_the_other_modules

Now how can I have the imported modules globally available?

For example:

conditional_import_modules(test='bar')
thirdmodule.myfunction()

Python Solutions


Solution 1 - Python

Imported modules are just variables - names bound to some values. So all you need is to import them and make them global with global keyword.

Example:

>>> math
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'math' is not defined
>>> def f():
...     global math
...     import math
...
>>> f()
>>> math
<module 'math' from '/usr/local/lib/python2.6/lib-dynload/math.so'>

Solution 2 - Python

You can make the imports global within a function like this:

def my_imports(module_name):
    globals()[module_name] = __import__(module_name)

Solution 3 - Python

You can use the built-in function __import__ to conditionally import a module with global scope.

To import a top level module (think: import foo):

def cond_import():
  global foo
  foo = __import__('foo', globals(), locals()) 

Import from a hierarchy (think: import foo.bar):

def cond_import():
  global foo
  foo = __import__('foo.bar', globals(), locals()) 

Import from a hierarchy and alias (think: import foo.bar as bar):

def cond_import():
  global bar
  foo = __import__('foo.bar', globals(), locals()) 
  bar = foo.bar

Solution 4 - Python

I've just had the similar problem, here is my solution:

class GlobalImport:

    def __enter__(self):
        return self

    def __call__(self):
        import inspect
        self.collector = inspect.getargvalues(inspect.getouterframes(inspect.currentframe())[1].frame).locals

    def __exit__(self, *args):
        globals().update(self.collector)

then, anywhere in the code:

with GlobalImport() as gi:
    import os, signal, atexit, threading, _thread
    # whatever you want it won't remain local
    # if only 
    gi()
    # is called before the end of this block

# there you go: use os, signal, ... from whatever place of the module

Solution 5 - Python

I like @badzil approach.

def global_imports(modulename,shortname = None, asfunction = False):
    if shortname is None: 
        shortname = modulename
    if asfunction is False:
        globals()[shortname] = __import__(modulename)
    else:        
        globals()[shortname] = eval(modulename + "." + shortname)

So something that is traditionally in a class module:

import numpy as np

import rpy2
import rpy2.robjects as robjects
import rpy2.robjects.packages as rpackages
from rpy2.robjects.packages import importr

Can be transformed into a global scope:

global_imports("numpy","np")

global_imports("rpy2")
global_imports("rpy2.robjects","robjects")
global_imports("rpy2.robjects.packages","rpackages")
global_imports("rpy2.robjects.packages","importr",True)

May have some bugs, which I will verify and update. The last example could also have an alias which would be another "shortname" or a hack like "importr|aliasimportr"

Solution 6 - Python

I like @rafał grabie approach. As it even support importing all. i.e. from os import *

(Despite it being bad practice XD )

Not allowed to comment, but here is a python 2.7 version.

Also removed the need to call the function at the end.

class GlobalImport:
    def __enter__(self):
        return self
    def __exit__(self, *args):
        import inspect
        collector = inspect.getargvalues(inspect.getouterframes(inspect.currentframe())[1][0]).locals
        globals().update(collector)

def test():
    with GlobalImport() as gi:
        ## will fire a warning as its bad practice for python. 
        from os import *

test()
print path.exists(__file__)

Solution 7 - Python

You could have this function return the names of the modules you want to import, and then use

mod == __import__(module_name)

Solution 8 - Python

Step-1: config.py, config_v2.py, rnd.py in same directory/folder

Step-2: config.py

HIGH_ATTENDANCE_COUNT_MIN = 0

Step-3: config_v2.py

HIGH_ATTENDANCE_COUNT_MIN = 5

Step-4: rnd.py

def versioning_test(v):
    global config

    if v == 'v1':
        config = __import__('config', globals(), locals()) 
    
    if v == 'v2':
        config = __import__('config_v2', globals(), locals())     

def version_test_in_another_function():
    print('version_test_in_another_function: HIGH_ATTENDANCE_COUNT_MIN: ', config.HIGH_ATTENDANCE_COUNT_MIN)
 

versioning_test("v2")
version_test_in_another_function()

Step-5: $ python3 rnd.py

<<output>>: version_test_in_another_function: HIGH_ATTENDANCE_COUNT_MIN:  5

Solution 9 - Python

I like the answer from @maxschlepzig.

There is a bug in the approach that if you directly import a function it will not work. For example,

global_imports("tqdm", "tqdm, True)

does not work, because the module is not imported. And this

global_imports("tqdm")
global_imports("tqdm", "tqdm, True)

works.

I change @maxschlepzig's answer a bit. Using fromlist so you can load function or module with "From" statement in a uniform way.

def global_imports(object_name: str,
                   short_name: str = None,
                   context_module_name: str = None):
    """import from local function as global import

    Use this statement to import inside a function,
    but effective as import at the top of the module.

    Args:
        object_name: the object name want to import,
                     could be module or function
        short_name: the short name for the import
        context_module_name: the context module name in the import

    example usage:
    import os -> global_imports("os")
    import numpy as np -> global_imports("numpy", "np")
    from collections import Counter ->
        global_imports("Counter", None, "collections")
    from google.cloud import storage ->
        global_imports("storage", None, "google.cloud")

    """
    if not short_name:
        short_name = object_name
    if not context_module_name:
        globals()[short_name] = __import__(object_name)
    else:
        context_module = __import__(context_module_name,
                                    fromlist=[object_name])
        globals()[short_name] = getattr(context_module, object_name)

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionGiovanni Di MiliaView Question on Stackoverflow
Solution 1 - PythonRoman BodnarchukView Answer on Stackoverflow
Solution 2 - PythonbadzilView Answer on Stackoverflow
Solution 3 - PythonmaxschlepzigView Answer on Stackoverflow
Solution 4 - Pythonrafał grabieView Answer on Stackoverflow
Solution 5 - PythonmshafferView Answer on Stackoverflow
Solution 6 - PythonJanView Answer on Stackoverflow
Solution 7 - PythonChrisBView Answer on Stackoverflow
Solution 8 - PythonArunDhwaj IIITHView Answer on Stackoverflow
Solution 9 - PythonYeu-Chern HarnView Answer on Stackoverflow