python中import module 和 from module import * 是一样的吗?

在开发的过程中碰到了一个有趣的问题。看下面这段代码:

LOCAL = None
try:
      from local_setting import *
except ImportError as e:
   logging.exception(e)
   pass
# 这里只有线上才会传LOG_FILE
print("Local = " + str(LOCAL))

local_setting.py

LOCAL = True

print("LOCAL =" + str(LOCAL))

print的结果为:

None
LOCAL =True
Local = True

说明local_setting.py中的LOCAL的namespace和主程序是一样的(这里是不是有点奇怪)。

然后把 from local_setting import * 改成import local_setting,执行

None
LOCAL =True
Local = None

这就是说local_setting.py中的LOCAL的namespace和主程序中的LOCAL又不一样了。

查了一下stackoverflow,有人这么回答:

There's a hell of a difference between importing specific named identifiers 'from module import X,Y,Z vs 'from module import *. The latter pollutes your namespace and can give unpredictable results depending on what's going on in module. Worse still is doing from module import * with multiple modules. – 
smci

有人回答:

Even though many people already explained about import vs import from, I want to try to explain a bit more about what happens under the hood, and where all the places it changes are.

import foo:
Imports foo, and creates a reference to that module in the current namespace. Then you need to define completed module path to access a particular attribute or method from inside the module.

E.g. foo.bar but not bar

from foo import bar:
Imports foo, and creates references to all the members listed (bar). Does not set the variable foo.

E.g. bar but not baz or foo.baz

from foo import *:
Imports foo, and creates references to all public objects defined by that module in the current namespace (everything listed in __all__ if __all__ exists, otherwise everything that doesn't start with _). Does not set the variable foo.

E.g. bar and baz but not _qux or foo._qux.

Now let’s see when we do import X.Y:

>>> import sys
>>> import os.path
Check sys.modules with name os and os.path:

>>> sys.modules['os']
<module 'os' from '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/os.pyc'>
>>> sys.modules['os.path']
<module 'posixpath' from '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/posixpath.pyc'>
Check globals() and locals() namespace dicts with os and os.path:

>>> globals()['os']
<module 'os' from '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/os.pyc'>
>>> locals()['os']
<module 'os' from '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/os.pyc'>
>>> globals()['os.path']
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
KeyError: 'os.path'
>>>
From the above example we found that only os is inserted in the local and global namespace. So, we should be able to use:

>>> os
<module 'os' from
  '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/os.pyc'>
>>> os.path
<module 'posixpath' from
 '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/posixpath.pyc'>
>>>
But not path.

>>> path
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'path' is not defined
>>>
Once you delete the os from locals() namespace, you won't be able to access os as well as os.path even though they exist in sys.modules:

>>> del locals()['os']
>>> os
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'os' is not defined
>>> os.path
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'os' is not defined
>>>
Now let's talk about import from:
from:
>>> import sys
>>> from os import path
Check sys.modules with os and os.path:
>>> sys.modules['os']
<module 'os' from '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/os.pyc'>
>>> sys.modules['os.path']
<module 'posixpath' from '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/posixpath.pyc'>
We found that in sys.modules we found as same as we did before by using import name

OK, let's check how it looks like in locals() and globals() namespace dicts:

>>> globals()['path']
<module 'posixpath' from '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/posixpath.pyc'>
>>> locals()['path']
<module 'posixpath' from '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/posixpath.pyc'>
>>> globals()['os']
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
KeyError: 'os'
>>>
You can access by using name path not by os.path:

>>> path
<module 'posixpath' from '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/posixpath.pyc'>
>>> os.path
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'os' is not defined
>>>
Let's delete 'path' from locals():

>>> del locals()['path']
>>> path
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'path' is not defined
>>>
One final example using an alias:

>>> from os import path as HELL_BOY
>>> locals()['HELL_BOY']
<module 'posixpath' from '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/posixpath.pyc'>
>>> globals()['HELL_BOY']
<module 'posixpath' from /System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/posixpath.pyc'>
>>>
And no path defined:

>>> globals()['path']
Traceback (most recent call last):
 File "<stdin>", line 1, in <module>
KeyError: 'path'
>>>

也就是说 from module import * 这种是把import里的对象放在主程序的namespace的。

https://stackoverflow.com/questions/710551/use-import-module-or-from-module-import

 

posted @ 2022-04-09 18:27  zjhgx  阅读(206)  评论(0编辑  收藏  举报