前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >python import 机制

python import 机制

作者头像
py3study
发布2020-01-13 10:26:40
4630
发布2020-01-13 10:26:40
举报
文章被收录于专栏:python3

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

代码语言:javascript
复制
>>> 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集合,这样做的话就是一次导入,其他地方就不用导入啦

代码语言:javascript
复制
>>> 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的路径下找了,就快了很多

代码语言:javascript
复制
>>> 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符号

代码语言:javascript
复制
>>> 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()输出的当前空间

代码语言:javascript
复制
>>> 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的。

代码语言:javascript
复制
>>> 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

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2019/08/11 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档