python import 机制

发布时间:2019-08-11 11:23:40编辑:auto阅读(1778)


    Python 环境初始化过程中就会将sys module加载到内存中,但是为了local空间更干净,需要用户亲自导入,通知python.module对象实际上是一个dict在维护着,hello.__dict__打印出属性和属性值,hello.__builtins__其实就是__builtins__.__dict__,
     

    1. >>> type(__builtins__) 
    2. <type 'module'
    3. >>> type(hello.__builtins__) 
    4. <type 'dict'
    5. liaoxinxi@tbase /home/liaoxinxi/start $ ls 
    6. hello.py hello.pyc world.py world.pyc 
    7. liaoxinxi@tbase /home/liaoxinxi/start $ touch __init__.py 


    嵌套导入
    只会影响到自己的本地空间,所有的import操作,不管在什么地方,时间都会影响到全局module集合,这样做的话就是一次导入,其他地方就不用导入啦

    1. >>> import world 
    2. 1 
    3. >>> dir(world) 
    4. ['__builtins__''__doc__''__file__''__name__''__package__''a''hello''sys'
    5. >>> dir(world.hello) 
    6. ['__builtins__''__doc__''__file__''__name__''__package__''a''b'
    7. >>> import sys 
    8. >>> sys.modules['hello'
    9. <module 'hello' from 'hello.pyc'
    10. >>> id(world.hello) 
    11. 3075426604L 
    12. >>> id(sys.modules['hello']) 
    13. 3075426604L 
    14. >>> import hello 
    15. >>> id(hello) 
    16. 3075426604L 



    package机制
    在module的基础上python增加了package的机制,如果说module是文件的话,那package就是文件夹机制,必须在文件夹有__init__.py文件存在,在导入start.hello后并在sys.modules导入start下面的其他模块,这和module有点不一样,dir(start)的时候已经有了__path__属性,这个属性就是告诉接下来的导入如import start.world,只会在start的路径下找了,就快了很多

    1. >>> import start.hello 
    2. >>> dir() 
    3. ['__builtins__''__doc__''__name__''__package__''start'
    4. >>> dir(start) 
    5. ['__builtins__''__doc__''__file__''__name__''__package__''__path__''hello'
    6. >>> sys.modules['start.world'
    7. Traceback (most recent call last): 
    8. File "<stdin>", line 1in <module> 
    9. NameError: name 'sys' is not defined 
    10. >>> import sys 
    11. >>> sys.modules['start.world'
    12. Traceback (most recent call last): 
    13. File "<stdin>", line 1in <module> 
    14. KeyError: 'start.world' 
    15. >>> sys.modules['start.hello'
    16. <module 'start.hello' from 'start/hello.pyc'
    17. >>> id(start) 
    18. 3075320012L 
    19. >>> id(start.hello) 
    20. 3075320108L 
    21. >>> id(sys.modules['start.hello']) 
    22. 3075320108L 



    from和imort关系
    from start import hello,其实本质都是是一样的,都是导入了start.hello,只是在local空间加入的符号不一样,from是加入hello,对应着start.hello,而import start.hello则是加入start符号

    1. >>> dir() 
    2. ['__builtins__''__doc__''__name__''__package__'
    3. >>> from start import hello 
    4. >>> dir() 
    5. ['__builtins__''__doc__''__name__''__package__''hello'
    6. >>> import sys 
    7. >>> sys.modules['hello'
    8. Traceback (most recent call last): 
    9. File "<stdin>", line 1in <module> 
    10. KeyError: 'hello' 
    11. >>> sys.modules['start.hello'
    12. <module 'start.hello' from 'start/hello.pyc'
    13. >>> sys.modules['start'
    14. <module 'start' from 'start/__init__.pyc'



    精确导入
    精确控制某个package下的module的某个属性的导入,在sys.modules下可以看到start,和start.hello到已经存在,只是在local空间,只能用到符号a,再仔细看看,其实hello也在当前空间中可用,也就是说sys.modules下存的就是module(包括module和package,不包括module的具体属性),dir()输出的当前空间

    1. >>> from start.hello import a 
    2. >>> a 
    3. 1 
    4. >>> start.hello.b 
    5. Traceback (most recent call last): 
    6. File "<stdin>", line 1in <module> 
    7. NameError: name 'start' is not defined 
    8. >>> dir() 
    9. ['__builtins__''__doc__''__name__''__package__''a''hello''sys'
    10. >>> hello.b 
    11. 2 
    12. >>> sys.modules['start'
    13. <module 'start' from 'start/__init__.pyc'
    14. >>> sys.modules['start.hello'
    15. <module 'start.hello' from 'start/hello.pyc'
    16. >>> sys.modules['hello'
    17. Traceback (most recent call last): 
    18. File "<stdin>", line 1in <module> 
    19. KeyError: 'hello' 
    20. >>> sys.modules['a'
    21. Traceback (most recent call last): 
    22. File "<stdin>", line 1in <module> 
    23. KeyError: 'a' 


    符号重命名
    没有将start加入到当前空间中,但是sys.module有,这和没重命名是不一样的,没有重命名的话,符号空间中是有start的。

    1. >>> import start.hello as hello 
    2. >>> dir() 
    3. ['__builtins__''__doc__''__name__''__package__''hello'
    4. >>> sys.modules['start.hello'
    5. Traceback (most recent call last): 
    6. File "<stdin>", line 1in <module> 
    7. NameError: name 'sys' is not defined 
    8. >>> import sys 
    9. >>> sys.modules['start.hello'
    10. <module 'start.hello' from 'start/hello.pyc'
    11. >>> sys.modules['hello'
    12. Traceback (most recent call last): 
    13. File "<stdin>", line 1in <module> 
    14. 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

     

     

关键字