Search code examples
pythonmodulepython-importlibimport-libraries

Importing variables from another file (importlib)?


I'm trying to import variables from another python files.

a.py - to be imported

text="Hello, world"
print("imported")

b.py - works, but I cannot have static name a

from a import *
print(text)

c.py - not work

import importlib

X = "a"

try:
    text = ""
    i = importlib.import_module(X)
    print(i)
    print(text)
except ImportError as err:
    print('Error:', err)

try:
    text = ""
    i = importlib.__import__(X , globals=True, locals=True, fromlist=[], level=0)
    print(i)
    print(text)
except ImportError as err:
    print('Error:', err)

try:
    text = ""
    i = importlib.__import__(X , globals=True, locals=True, fromlist=[text], level=0)
    print(i)
    print(text)
except ImportError as err:
    print('Error:', err)

ouptut is:

imported
<module 'a' from '/tmp/a.py'>

<module 'a' from '/tmp/a.py'>

<module 'a' from '/tmp/a.py'>

but text varible not working.

d.py - not work

X = "a"
from X import *
print(text)

Is possible to use importlib as from MODULE import *?


Solution

  • Star imports ("from xxx import *") are bad practice (and actively discouraged by pep08) and should only be used as a convenient shortcut in a Python shell for a quick inspection / experimentation / debugging.

    So your b.py code should either import the a module and use qualified path ie:

     # b.py
     import a
     print(a.text)
    

    or (at worst) explicitely import the desired name(s) from a:

    # b.py
    from a import text
    print(text)
    

    Note that this second solution won't work as expected fior mutable globals, since in that case text becomes a module-local name in b so if a.text is rebound (reassigned) somewhere else b.text will not be impacted. But mutable globals are evil anyway...

    Now assuming you do the RightThing and opt for the first solution (module import + qualified path), the "translation" using importlib would be:

    import importlib
    module_name = "a"
    module = importlib.import_module(module_name)
    print(module.text)
    

    FWIW, all your attempts at using importlib.__import__() are wrong - globals is supposed to be a dict, and fromlist shoud be a list of names (strings). But there are very few good reasons for using importlib.__import__() instead of importlib.import_module actually.