• 【Python】模块与包的组织


    模块与包

    模块和包是Python项目的核心,这里简单总结一些包和结构和使用。

    1. 将模块按层次组织成包

    将代码按照一定层次组成成包的形式。一个Python包的形式大致如下:

    zzz@ubuntu:~/my_learning$ tree my_project
    my_project
    ├── __init__.py
    ├── package1
    │   ├── a.py
    │   ├── b.py
    │   └── __init__.py
    └── package2
        ├── c.py
        └── __init__.py
    
    2 directories, 6 files
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    可以看到,包的创建很简单,就是在文件系统中创建一个目录结构,然后在每个目录下定义一个__init__.py文件。此时,就可以使用 import 语句来进行导入。

    zzz@ubuntu:~/my_learning$ python3
    Python 3.8.10 (default, Mar 15 2022, 12:22:08) 
    [GCC 9.4.0] on linux
    Type "help", "copyright", "credits" or "license" for more information.
    >>> import my_project
    >>> import my_project.package1
    >>> from my_project.package2 import c
    >>> 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    __init__.py文件会在模块导入模块时运行,比如,当执行 import my_project.package1.a 时,会在导入 a.py 文件之前,先导入 my_project/__init__.pymy_project/package1/__init__.py 文件。__init__.py文件可以留空,也可以包含代码。

    2. 模块的导入

    模块的导入最简单的形式就是:

    import module as md
    from module import A as a
    
    • 1
    • 2

    相对名称导入
    如果我们需要从包中的一个子模块中导入另一个子模块,可以使用相对名称。

    # a.py
    class A:
        def __str__(self):
            return "class A object"
    
    • 1
    • 2
    • 3
    • 4
    # b.py
    from . import a 
    class B(a.A):
        def __str__(self):
            return "class B object"
    
    • 1
    • 2
    • 3
    • 4
    • 5
    # b.py
    from ..package1 import a
    
    class C(a.A):
        def __str__(self):
            return "class C object"
    ...
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    import 语句中的 ... 语句可以视为指定目录名。 . 表示从当前目录中查找,..package1表示从 ../package1 目录中查找。这两个语法中能在 from XX import X语句中使用。
    精确控制导入
    用户可以使用 from module import * 语句导入模块或包,如果需要对导入的符号进行精确控制,可以使用变量 __all__ 显式列出可导出的符号名。只有列在 __all__ 中的符号才会被导入。

    # c.py
    from ..package1 import a
    
    
    class C(a.A):
        def __str__(self):
            return "class C object"
    
    class D:
        def __str__(self):
            return "class D object"
    
    # Only export 'C'
    __all__ = ['C']
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    可以看到,C 被成功导入,而 D 并没有导入。

    zzz@ubuntu:~/my_learning$ python3
    Python 3.8.10 (default, Mar 15 2022, 12:22:08) 
    [GCC 9.4.0] on linux
    Type "help", "copyright", "credits" or "license" for more information.
    >>> from my_project.package2.c import *
    >>> print( C() )
    class C object
    >>> print( D() )
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    NameError: name 'D' is not defined
    >>> 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    3. 将一个模块分解为多个文件

    我们可以通过 import my_module 语句导入一个模块,然后就可以通过 my_module.A() 的形式使用模块中的符号。现在,我们需要将 my_module 分解为多个单独的文件,然后仍然可以在通过 my_module.A() 的形式使用已经分解到不同文件中的符号。以 c.py 文件为例

    # c.py
    from ..package1 import a
    
    class C(a.A):
        def __str__(self):
            return "class C object"
    
    class D:
        def __str__(self):
            return "class D object"
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    可以使用 import 语句导入:

    zzz@ubuntu:~/my_learning$ python3
    Python 3.8.10 (default, Mar 15 2022, 12:22:08) 
    [GCC 9.4.0] on linux
    Type "help", "copyright", "credits" or "license" for more information.
    >>> import my_project.package2.c as c
    >>> 
    >>> print( c.C() )
    class C object
    >>> print( c.D() )
    class D object
    >>> 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    现在我们将 c.py 分解为两个文件,每个文件包含一个类的定义。首先,将c.py 替换成 目录 c,变成如下形式:
    修改前:

    zzz@ubuntu:~/my_learning/my_project$ tree package2
    package2
    ├── c.py
    └── __init__.py
    
    • 1
    • 2
    • 3
    • 4

    修改后:

    package2
    ├── c
    │   ├── c.py
    │   ├── d.py
    │   └── __init__.py
    └── __init__.py
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    其中:

    # my_project/package2/c/c.py 
    from my_project.package1 import a
    
    class C(a.A):
        def __str__(self):
            return "class C object
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    # my_project/package2/c/d.py 
    class D:
        def __str__(self):
            return "class D object"
    
    • 1
    • 2
    • 3
    • 4

    此时,可以使用 import 语句导入 c 模块,但是调用失败。

    zzz@ubuntu:~/my_learning$ python3
    Python 3.8.10 (default, Mar 15 2022, 12:22:08) 
    [GCC 9.4.0] on linux
    Type "help", "copyright", "credits" or "license" for more information.
    >>> import my_project.package2.c as c
    >>> print( c.D() )
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    AttributeError: module 'my_project.package2.c' has no attribute 'D'
    >>> print( c.C() )
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    AttributeError: module 'my_project.package2.c' has no attribute 'C'
    >>> 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    为解决这个问题,可以在 my_project/package2/c/__init__.py 文件中绑定两个文件。

    # my_project/package2/c/__init__.py
    from .c import C
    from .d import D
    
    • 1
    • 2
    • 3

    此时,就可以在拆分后,仍然可以向之前一样使用:

    zzz@ubuntu:~/my_learning$ python3
    Python 3.8.10 (default, Mar 15 2022, 12:22:08) 
    [GCC 9.4.0] on linux
    Type "help", "copyright", "credits" or "license" for more information.
    >>> import my_project.package2.c as c
    >>> print( c.C() )
    class C object
    >>> print( c.D() )
    class D object
    >>> 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
  • 相关阅读:
    中台框架模块开发实践-用 Admin.Core 代码生成器生成通用代码生成器的模块代码
    MySQL (2)
    信道复用技术
    EF7创建模型值生成篇
    MySQL bit类型解析
    Centos下安装 oracle11g 博客2
    Shiro介绍及其功能
    c#快速获取超大文件夹文件名
    Hadoop的HDFS的集群安装部署
    python中的GUI自动化工具介绍
  • 原文地址:https://blog.csdn.net/weixin_43276033/article/details/125494986