关于Python中的import(三)

上节介绍了 importlib.import_module(),和 package 的基础概念,本节深入理解导模块的机理以及简单了解 Namespace package

在 import 模块的时候,系统会首先到 sys.modules 里面去查找要导入的模块,sys.modules 是个什么东东呢,我们打印一下看看它是什么:

import sys

print(type(sys.modules))  # <class 'dict'>

sys.modules 是一个存放缓存模块的字典,打印一下会发现许多条目所有之前导入过的模块都在这个字典中。当我们导入一个模块时,会首先查看 sys.modules里面有没有缓存,如果有直接返回,搜索过程结束;如果没有,则继续查找。

例如导入模块 foo.bar.biz, 系统会首先导入中间模块 foo,然后是 foo.bar,最后是 foo.bar.biz, 然后 sys.modules 中会多出三条条目,键分别为 “foo”、“foo.bar”、“foo.bar.biz”,值为对应的模块对象,多次导入会拿到同一个模块对象,并且第一次导入模块时会执行模块内的代码。

假如在 sys.modules 中没有找到要导入的模块,那么系统就要进一步搜索模块,这里有很多具体细节,就不说了,总的来说就是如果是我们自己定义的模块,会往 sys.path 中去找

import sys

print(sys.path)

打印出的结果是一个列表,列表里面是一些路径,默认状态下第一个路径是我们启动 python 程序的工作目录,首先在这个目录下查找模块。例如导入 foo.bar.biz, 会首先在 sys.path 下寻找 foo 模块,找到后,再在 foo 的 __path__ 下查找bar, 再在 bar 的 __path__ 下查找 biz。

而 sys.path 是可以修改的,我们可以向里面 insert 搜索路径。

parent/
    main.py
    one/
        __init__.py
        mymodule.py
    two/
        __init__.py
    three/
        __init__.py

假设我们通过执行 main.py 启动 Python 程序,parent 为工作目录,这时需要在 main 模块中导入 mymodule 模块,需要 import one.mymodule, 假如在导入之前,执行 sys.path.append(‘./one’)

import sys

sys.path.append('./one')
import mymodule

这样就会直接在 parent/one/ 路径下查找到模块,但是注意这样创建的模块和通过 import one.mymodule 方式导入的模块不是同一个对象,在 sys.modules 中会对应两个不同的键值对。

Namespace package

Namespace package 与 Regular package 表面上的不同点是 Namespace package 下没有 __init__.py 文件, 还是用实例来说明

Lib/test/namespace_pkgs
    project1
        parent
            child
                one.py
    project2
        parent
            child
                two.py

这里两个 parent 和 两个 child package下都没有 __init__.py 文件,

>>> import sys
>>> sys.path += ['Lib/test/namespace_pkgs/project1', 'Lib/test/namespace_pkgs/project2']
>>> import parent.child.one
>>> parent.__path__
_NamespacePath(['Lib/test/namespace_pkgs/project1/parent', 'Lib/test/namespace_pkgs/project2/parent'])
>>> parent.child.__path__
_NamespacePath(['Lib/test/namespace_pkgs/project1/parent/child', 'Lib/test/namespace_pkgs/project2/parent/child'])
>>> import parent.child.two
>>>

每个 namespace package 的 __path__ 属性,都有两条。说白了此时就是通过 import parent.child.xxx.py 导入模块时,有两条可搜索的路径,在 sys.path += [‘Lib/test/namespace_pkgs/project1’, ‘Lib/test/namespace_pkgs/project2’] 执行后,sys.path中就多了两条搜索路径,这两条搜索路径下有相同的 namespace package 结构,于是乎就发生了些不可描述的事情,大家自行体会。namespace package 的 __path__ 我们是不能去修改的,系统会自动动态更新。

import 的内容就简单说到这,关于 import 还有些更深入的内容,就暂时不去探究了,以后如果遇到再来补充。


参老资料:
官方文档 3.6.2
https://www.python.org/dev/peps/pep-0420/

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值