• 一、什么是包

    随着模块数目的增多,把所有模块不加区分地放到一起也是极不合理的,于是Python为我们提供了一种把模块组织到一起的方法,即创建一个包。包就是一个含有init.py文件的文件夹,文件夹内可以组织子模块或子包,例如

    pool/                #顶级包
    ├── __init__.py    
    ├── futures          #子包
       ├── __init__.py
       ├── process.py
       └── thread.py
    └── versions.py      #子模块

    需要强调的是

    #1. 在python3中,即使包下没有__init__.py文件,import 包仍然不会报错,而在python2中,包下一定要有该文件,否则import 包报错

    #2. 创建包的目的不是为了运行,而是被导入使用,记住,包只是模块的一种形式而已,包的本质就是一种模块

    接下来我们就以包pool为例来介绍包的使用,包内各文件内容如下

    # process.py
    class ProcessPoolExecutor:
        def __init__(self,max_workers):
            self.max_workers=max_workers

        def submit(self):
            print('ProcessPool submit')

    # thread.py
    class ThreadPoolExecutor:
        def __init__(self, max_workers):
            self.max_workers = max_workers

        def submit(self):
            print('ThreadPool submit')

    # versions.py
    def check():
        print('check versions’)

    # __init__.py文件内容均为空

    二、包的使用

    首次导入包(如import pool)同样会做三件事:

    1、执行包下的init.py文件

    2、产生一个新的名称空间用于存放init.py执行过程中产生的名字

    3、在当前执行文件所在的名称空间中得到一个名字pool,该名字指向init.py的名称空间,例如pool.xxx和pool.yyy中的xxx和yyy都是来自于pool下的init.py,也就是说导入包时并不会导入包下所有的子模块与子包

    import pool

    pool.versions.check() #抛出异常AttributeError
    pool.futures.process.ProcessPoolExecutor(3) #抛出异常AttributeError

    pool.versions.check()要求pool下有名字versions,进而pool.versions下有名字check。pool.versions下已经有名字check了,所以问题出在pool下没有名字versions,这就需要在pool下的init.py中导入模块versions

    三、绝对导入和相对导入

    1、绝对导入:以顶级包为起始

    #pool下的__init__.py
    from pool import versions

    2、相对导入:.代表当前文件所在的目录,..代表当前目录的上一级目录,依此类推

    #pool下的__init__.py
    from . import versions
    pool/                #顶级包
    ├── __init__.py    
    ├── futures          #子包
       ├── __init__.py
       ├── process.py
       └── thread.py
    └── versions.py      #子模块

    同理,针对pool.futures.process.ProcessPoolExecutor(3),则需要

    #操作pool下的__init__.py,保证pool.futures
    from . import futures #或from pool import futures

    #操作futrues下的__init__.py,保证pool.futures.process
    from . import process #或from pool.futures import process

    例1:

    import pool.futures #拿到名字pool.futures指向futures下的__init__.py

    pool.futures.xxx #要求futures下的__init__.py中必须有名字xxx

    例2:

    import pool.futures.thread #拿到名字pool.futures.thread指向thread.py

    thread_pool=pool.futures.thread.ThreadPoolExecutor(3)
    thread_pool.submit()

    相对导入只能用from module import symbol的形式,import ..versions语法是不对的,且symbol只能是一个明确的名字

    from pool import futures.process #语法错误
    from pool.futures import process #语法正确

    针对包内部模块之间的相互导入推荐使用相对导入,需要特别强调:

    1、相对导入只能在包内部使用,用相对导入不同目录下的模块是非法的

    2、无论是import还是from-import,但凡是在导入时带点的,点的左边必须是包,否则语法错误


  • 相关阅读:
    作业第十六周
    web、app、小程序测试异同点
    接口测试用例演进
    Python中“if __name__=='__main__':”
    iPhone发布内测程序的方法
    我的2020
    python 参数笔记 --> 位置参数 关键字参数 命名参数 形式参数 默认参数 可变参数 可选参数 位置顺序
    uwsgi 热部署 热启动 热更新
    Supervisor 进程管理工具 笔记
    spring Boot----注解驱动开发
  • 原文地址:https://www.cnblogs.com/bailongcaptain/p/12593400.html
Copyright © 2020-2023  润新知