Python Forum

Full Version: NameError – function doesn't recognize imported modules
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
I was trying out using keywords encoded in a string by using exec() and eval() functions.
I got an error.

For this time the keywords I'm working with is import.
The problem seems to be related with scopes.


def imp3(*Names):
    for name in Names:
        exec("import "+name)
        print(eval(name))  #for debugging
    return tuple(eval(name) for name in Names)

os,json,time= imp3("os","json","time")

Output:
<module 'os' from 'C:\\Program Files\\WindowsApps\\PythonSoftwareFoundation.Python.3.8_3.8.1776.0_x64__qbz5n2kfra8p0\\lib\\os.py'> <module 'json' from 'C:\\Program Files\\WindowsApps\\PythonSoftwareFoundation.Python.3.8_3.8.1776.0_x64__qbz5n2kfra8p0\\lib\\json\\__init__.py'> <module 'time' (built-in)>
Error:
Traceback (most recent call last): File "G:\Builtins.py", line 25, in <module> os,json,time= imp3("os","json","time") File "G:\Builtins.py", line 23, in imp3 return tuple(eval(name) for name in Names) File "G:\Builtins.py", line 23, in <genexpr> return tuple(eval(name) for name in Names) File "<string>", line 1, in <module> NameError: name 'os' is not defined
I've added a print statement (as you can see), so that I'm sure that modules got indeed imported. Cool
And so they did... got imported. Smile
You can imagine my face when in the next row they were not recognised. Confused

Could any smart guy or girl explain to me what has happened?Wall
Why do you want to do anything with exec or eval in the first place, rather than importing normally?
I'm not completely certain what is happening, but it looks like the tuple construction is getting confused by the generator. Building up the tuple in the loop "works".

That said, this whole thing is highly suspect.

def imp3(*Names):
    modules = tuple()
    for name in Names:
        exec("import "+name)
        print(eval(name))
        modules += (eval(name),)
    return modules

os,json, time = imp3("os","json","time")
print(os.name)
print(time.time())
Output:
<module 'os' from '/usr/lib/python3.8/os.py'> <module 'json' from '/usr/lib/python3.8/json/__init__.py'> <module 'time' (built-in)> posix 1606725446.456842
1. as asked by @ndc85430 - why would you import like this in the first place?
2. you are right - it's a scope issue. that's one of the reasons why the recommended way for imports is at the top of the module

def spam():
    import os
    print(os.getcwd())

spam()
print(os.getcwd())
3. if you really, really, really need to do something like this - don't use eval or exec. use importlib modue
import importlib

def bulk_import(*modules):
    return (importlib.import_module(some_module) for some_module in modules)
    
os, datetime = bulk_import("os", 'datetime')
print(os.getcwd())
(Nov-30-2020, 08:53 AM)buran Wrote: [ -> ]1. as asked by @ndc85430 - why would you import like this in the first place?

For building my own understanding, buran.
As I have written in the beginning: "I was trying out using keywords encoded in a string by using exec() and eval() functions.". Also wanted to make modules transcend the scope zone as a part of the experiment.


I think bowlofred answer is the key here.
But I would like also to acknowledge you for this script with importlib.

Smile Again thank you.