user2234026
user2234026

Reputation: 11

Force import from a function in another module

Okay I'm trying to do something with python version 3.3.2 I'm trying to import module so I don't have to restart the shell. The following is just an example the final code will be able to change:

def importing():
    x = compile('import sys',"<string","exec")
    exec(x)
    return True

The problem with this is when I call on this using test.importing() it returns True but when i do sys it says:

 Traceback (most recent call last):
  File "<pyshell#74>", line 1, in <module>
    sys
NameError: name 'sys' is not defined

Whats confusing me is though it works perfectly fine in the shell, any ideas or advice would be very thankful to me.

Upvotes: 1

Views: 414

Answers (3)

zhangyangyu
zhangyangyu

Reputation: 8620

exec if no locals and globals passed, it executes in the current scope. So, your import sys import the sys module in the importing scope. See the code:

>>> def c():
...     exec('import sys')
...     print(locals())
...     print(globals())
... 
>>> c()
{'sys': <module 'sys' (built-in)>}
{'__builtins__': <module 'builtins'>, '__package__': None, '__name__': '__main__', '__loader__': <class '_frozen_importlib.BuiltinImporter'>, 'c': <function c at 0x7faa068e0320>, 'b': <function b at 0x7faa068e45f0>, 'a': <function a at 0x7faa066abe60>, 'd': <function d at 0x7faa068f6200>, 'inspect': <module 'inspect' from '/usr/lib64/python3.3/inspect.py'>, '__doc__': None}

See, the sys is in the local scope but not the global scope. But note, the import is excuted dynamically, even if it is in the local scope, you can not call the sys directly in the function. The call will end up with an error, can not find the sys in the global scope:

>>> def a():
...     exec('import sys')
...     if sys:
...             return True
...     else:   
...             return False
... 
>>> a()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 3, in a
NameError: global name 'sys' is not defined

Instead, you should use locals():

>>> def b():
...     exec('import sys')
...     if locals()['sys']:
...             return True
...     else:
...             return False
... 
>>> b()
True

Last, I think using exec is not a good choice. Just like others have mentioned, using __importing__.

Upvotes: 1

djf
djf

Reputation: 6757

If you want to dynamically import modules you can use __import__.

Example Dive into Python:

>>> sys = __import__('sys')           
>>> os = __import__('os')
>>> re = __import__('re')
>>> unittest = __import__('unittest')
>>> sys                               
>>> <module 'sys' (built-in)>
>>> os
>>> <module 'os' from '/usr/local/lib/python2.2/os.pyc'>

Upvotes: 2

Fredrik H&#229;&#229;rd
Fredrik H&#229;&#229;rd

Reputation: 2925

if you just want to reload a module, you can do

from imp import reload
reload(sys)

Upvotes: 2

Related Questions