python的import机制

Python中所有加载到内存的模块都放在sys.modules。当import一个模块时首先会在这个列表中查找是否已经加载了此模块,如果加载了则只是将模块的名字加入到正在调用import的模块的Local名字空间中。如果没有加载则从sys.path目录中按照模块名称查找模块文件,模块文件可以是py、pyc、pyd,找到后将模块载入内存,并加入到sys.modules中,并将名称导入到当前的Local名字空间。

可以看出了,一个模块不会重复载入。多个不同的模块都可以用import引入同一个模块到自己的Local名字空间,其实背后的PyModuleObject对象只有一个。

嵌套Import
嵌套import,我分两种情况,一种是:本模块导入A模块(import A),而A中又有import语句,会激活另一个import动作,如import B,而B模块又可以import其他模块,一直下去。

对这种嵌套比较容易理解,注意一点就是各个模块的Local名字空间是独立的,所以上面的例子,本模块import A完了后本模块只能访问模块A,不能访问B及其他模块。虽然模块B已经加载到内存了,如果要访问还要在明确的在本模块中import B。

另外一种嵌套指,在模块A中import B,而在模块B中import A。这时会怎么样呢?这个在Python列表中由RobertChen给出了详细解释,抄录如下:
[A.py]
from B import D
class C:pass

[B.py]
from A import C
class D:pass

为什么执行A的时候不能加载D呢?

如果将A.py改为:import B就可以了。

这是怎么回事呢?

RobertChen:这跟Python内部import的机制是有关的,具体到from B import D,Python内部会分成几个步骤:

  • 在sys.modules中查找符号"B"
  • 如果符号B存在,则获得符号B对应的module对象。
    从的__dict__中获得符号"D"对应的对象,如果"D"不存在,则抛出异常
  • 如果符号B不存在,则创建一个新的module对象,注意,这时,module对象的__dict__为空。执行B.py中的表达式,填充的__dict__ 。
    从的__dict__中获得"D"对应的对象,如果"D"不存在,则抛出异常。

所以,这个例子的执行顺序如下:

  • 执行A.py中的from B import D
    由于是执行的python A.py,所以在sys.modules中并没有存在,首先为B.py创建一个module对象(),注意,这时创建的这个module对象是空的,里边啥也没有,在Python内部创建了这个module对象之后,就会解析执行B.py,其目的是填充这个dict。
  • 执行B.py中的from A import C
    在执行B.py的过程中,会碰到这一句,首先检查sys.modules这个module缓存中是否已经存在了,由于这时缓存还没有缓存,所以类似的,Python内部会为A.py创建一个module对象(),然后,同样地,执行A.py中的语句。
  • 再次执行A.py中的from B import D
    这时,由于在第1步时,创建的对象已经缓存在了sys.modules中,所以直接就得到了,但是,注意,从整个过程来看,我们知道,这时还是一个空的对象,里面啥也没有,所以从这个module中获得符号"D"的操作就会抛出异常。如果这里只是importB,由于"B"这个符号在sys.modules中已经存在,所以是不会抛出异常的。

另外测试的例子:

    # -*- coding:utf-8 -*-
    
    # A.py
    def action_a():
    	print '333'
    	print B.action_b.__name__
    print '555'
    from B import action_b
    print '666'
    # -*- coding:utf-8 -*-
    
    #B.py
    def action_b():
    	print '222'
    	print A.action_a.__name__
    print '111'
    from A import action_a
    print '444'

执行A.py
在这里插入图片描述
执行B.py
在这里插入图片描述

参考链接:
https://blog.csdn.net/zbyufei/article/details/5894645
https://www.cnblogs.com/yan-lei/p/7828871.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值