当前位置 主页 > 网站技术 > 代码类 >

    解析Python3中的Import

    栏目:代码类 时间:2019-11-09 21:04

    Python import的搜索路径

    import的搜索路径为:

    搜索「内置模块」(built-in module) 搜索 sys.path 中的路径 而sys.path在初始化时,又会按照顺序添加以下路径:

    foo.py 所在目录(如果是软链接,那么是真正的 foo.py 所在目录)或当前目录;

    环境变量 PYTHONPATH中列出的目录(类似环境变量 PATH,由用户定义,默认为空);
    site 模块被 import 时添加的路径1(site 会在运行时被自动 import)。

    import site 所添加的路径一般是 XXX/site-packages。如果懒得记 sys.path 的初始化过程,可以简单的认为 import 的查找顺序是:

    内置模块

    .py 文件所在目录
    pip 或 easy_install 安装的包

    绝对导入和相对导入

    绝对导入和相对导入的关系可以类比绝对路径和相对路径。

    绝对导入的格式为:

    import A.B
    或
    from A import B

    相对导入格式为:

    from . import B
    或
    from ..A import B

    其中,点号.代表当前模块,..代表上层模块,…代表上上层模块,依次类推。

    模块的执行方式

    模块的执行可以有两种方式:直接执行和以模块执行,即:

    python example/foo.py
    或
    python -m example.foo
    

    注意,以模块执行时,一定要有包的概念,即example一定是个包,而foo是这个包下的模块,这样才能顺利执行。

    包和模块

    模块: 一个 .py 文件就是一个模块(module)

    包: init .py 文件所在目录就是包(package)

    各种情形测试

    模块直接导入

    即模块所在的目录都不是一个包结构,各个模块都是独立的,比如以下的目录结构:

    D:\LEARN\IMPORT_TEST\TEST1
    ├─pack1
    │  modu1.py
    └─pack2
      modu2.py


    modu1.py中的内容为:

    import sys
    sys.path.append("D:\\learn\\import_test\\TEST1\\pack2")
    from modu2 import hello2
    hello2()


    modu2.py中的内容为:

    def hello2():
     print("hello, I am module 2")


    注意在modu1中一定加上sys.path.append那部分内容,即根据上面的描述,一定要让modu1能找到modu2才行,否则就会出现如下错误:

    ModuleNotFoundError: No module named 'modu2'

    此时进入pack1目录下,以直接执行或模块执行的方式都可以顺利输出。

    包外导入

    将上面两个模块所在的目录都变为包结构,即:

    D:\LEARN\IMPORT_TEST\TEST2
    ├─pack1
    │  modu1.py
    │  __init__.py
    └─pack2
      modu2.py
      __init__.py


    此时也能顺利执行,同时比上面非包结构的多出来一条执行方式,即:

    python -m pack1.modu1

    即以包名+模块名的方式执行。

    上面两种情形,即模块与模块、包与包都是相互独立的关系,也就没有相对导入的意义。

    如果是在一个包内的不同模块的导入,那么最自然的就是使用相对导入。

    包内相对导入

    D:\LEARN\IMPORT_TEST\Test3
    │ __init__.py
    │
    ├─pack1
    │  modu1.py
    │  __init__.py
    │
    └─pack2
      modu2.py
      __init__.py


    此时modu1.py中的内容为:

    from ..pack2.modu2 import hello2
    hello2()