python import 机制
python 环境初始化过程中就会将sys module加载到内存中,但是为了local空间更干净,需要用户亲自导入,通知Python.module对象实际上是一个dict在维护着,hello.__dict__打印出属性和属性值,hello.__builtins__其实就是__builtins__.__dict__,
- >>> type(__builtins__)
- <type 'module'>
- >>> type(hello.__builtins__)
- <type 'dict'>
- liaoxinxi@tbase /home/liaoxinxi/start $ ls
- hello.py hello.pyc world.py world.pyc
- liaoxinxi@tbase /home/liaoxinxi/start $ touch __init__.py
嵌套导入
只会影响到自己的本地空间,所有的import操作,不管在什么地方,时间都会影响到全局module集合,这样做的话就是一次导入,其他地方就不用导入啦
- >>> import world
- 1
- >>> dir(world)
- ['__builtins__', '__doc__', '__file__', '__name__', '__package__', 'a', 'hello', 'sys']
- >>> dir(world.hello)
- ['__builtins__', '__doc__', '__file__', '__name__', '__package__', 'a', 'b']
- >>> import sys
- >>> sys.modules['hello']
- <module 'hello' from 'hello.pyc'>
- >>> id(world.hello)
- 3075426604L
- >>> id(sys.modules['hello'])
- 3075426604L
- >>> import hello
- >>> id(hello)
- 3075426604L
package机制
在module的基础上python增加了package的机制,如果说module是文件的话,那package就是文件夹机制,必须在文件夹有__init__.py文件存在,在导入start.hello后并在sys.modules导入start下面的其他模块,这和module有点不一样,dir(start)的时候已经有了__path__属性,这个属性就是告诉接下来的导入如import start.world,只会在start的路径下找了,就快了很多
- >>> import start.hello
- >>> dir()
- ['__builtins__', '__doc__', '__name__', '__package__', 'start']
- >>> dir(start)
- ['__builtins__', '__doc__', '__file__', '__name__', '__package__', '__path__', 'hello']
- >>> sys.modules['start.world']
- Traceback (most recent call last):
- File "<stdin>", line 1, in <module>
- NameError: name 'sys' is not defined
- >>> import sys
- >>> sys.modules['start.world']
- Traceback (most recent call last):
- File "<stdin>", line 1, in <module>
- KeyError: 'start.world'
- >>> sys.modules['start.hello']
- <module 'start.hello' from 'start/hello.pyc'>
- >>> id(start)
- 3075320012L
- >>> id(start.hello)
- 3075320108L
- >>> id(sys.modules['start.hello'])
- 3075320108L
from和imort关系
from start import hello,其实本质都是是一样的,都是导入了start.hello,只是在local空间加入的符号不一样,from是加入hello,对应着start.hello,而import start.hello则是加入start符号
- >>> dir()
- ['__builtins__', '__doc__', '__name__', '__package__']
- >>> from start import hello
- >>> dir()
- ['__builtins__', '__doc__', '__name__', '__package__', 'hello']
- >>> import sys
- >>> sys.modules['hello']
- Traceback (most recent call last):
- File "<stdin>", line 1, in <module>
- KeyError: 'hello'
- >>> sys.modules['start.hello']
- <module 'start.hello' from 'start/hello.pyc'>
- >>> sys.modules['start']
- <module 'start' from 'start/__init__.pyc'>
精确导入
精确控制某个package下的module的某个属性的导入,在sys.modules下可以看到start,和start.hello到已经存在,只是在local空间,只能用到符号a,再仔细看看,其实hello也在当前空间中可用,也就是说sys.modules下存的就是module(包括module和package,不包括module的具体属性),dir()输出的当前空间
- >>> from start.hello import a
- >>> a
- 1
- >>> start.hello.b
- Traceback (most recent call last):
- File "<stdin>", line 1, in <module>
- NameError: name 'start' is not defined
- >>> dir()
- ['__builtins__', '__doc__', '__name__', '__package__', 'a', 'hello', 'sys']
- >>> hello.b
- 2
- >>> sys.modules['start']
- <module 'start' from 'start/__init__.pyc'>
- >>> sys.modules['start.hello']
- <module 'start.hello' from 'start/hello.pyc'>
- >>> sys.modules['hello']
- Traceback (most recent call last):
- File "<stdin>", line 1, in <module>
- KeyError: 'hello'
- >>> sys.modules['a']
- Traceback (most recent call last):
- File "<stdin>", line 1, in <module>
- KeyError: 'a'
符号重命名
没有将start加入到当前空间中,但是sys.module有,这和没重命名是不一样的,没有重命名的话,符号空间中是有start的。
- >>> import start.hello as hello
- >>> dir()
- ['__builtins__', '__doc__', '__name__', '__package__', 'hello']
- >>> sys.modules['start.hello']
- Traceback (most recent call last):
- File "<stdin>", line 1, in <module>
- NameError: name 'sys' is not defined
- >>> import sys
- >>> sys.modules['start.hello']
- <module 'start.hello' from 'start/hello.pyc'>
- >>> sys.modules['hello']
- Traceback (most recent call last):
- File "<stdin>", line 1, in <module>
- KeyError: 'hello'
总结:import 机制的实现:
维护一个全家的module pool
解析和搜索module路径的书状结构
对不同文件格式的动态加载机制
归根到底就是import x.y.z,而from,as只会改变当前的命名空间,import x.y.z会将x,x.y,x.y,z导入sys.modules,而命名空间只有x.y.z
另外import * from a package,并不会导入package下面的模块,除非在__init__.py添加了__all__=[“hello”,“world”],这样就会导入hello和world
相关文章