您的位置:首页 > 编程语言 > Python开发

python import 机制

2012-11-02 09:42 417 查看
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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息