python import 机制

2023-01-31 01:01:04 python import 机制


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

 

 

相关文章