python小知识-模块

简介: 在《失控》中提到一个几千万行的程序(操作系统)要想没有bug是很难,减少bug的解决方案就是不断的拆分功能项,直到不能拆分为止,只要保证拆分的最小功能项通过一定的单元测试,就可能消费bug(当然还有集成性和系统性的bug)。《失控》里说的就是现代软件工程的模块化开发方式,在面向对象开发以及架构设计上都会涉及到。

1. 什么是模块

在《失控》中提到一个几千万行的程序(操作系统)要想没有bug是很难,减少bug的解决方案就是不断的拆分功能项,直到不能拆分为止,只要保证拆分的最小功能项通过一定的单元测试,就可能消费bug(当然还有集成性和系统性的bug)。《失控》里说的就是现代软件工程的模块化开发方式,在面向对象开发以及架构设计上都会涉及到。

那什么是模块?从上面可知,模块可以理解为独立的功能拆分,可根据具体业务拆分成大模块和小模块。

举几个例子:

一个入库系统可以拆分成前端的展示模块,后端的业务处理以及中间的交互层;后端业务处理可以拆分成数据处理(如数据库操作等)和具体的不同的业务模块(如计费模块,折扣模块,物料模块等);

一个深度学习的训练可以拆分:

  • 数据模块:负责处理和加载数据
  • 网络模块:负责构建深度学习网络
  • 训练模块:负责调用数据、构建网络以及设计损失和优化器,以及梯度方向传播,还有模型参数的保存和加载等
  • 测试推理模块:负责模型测试和推理
  • 功能模块:比如常见的utils

以上可能是比较大的模块,还可以细分成更细的小的模块;

  • 比如数据模块,可以拆分成小的特定数据的模块,比如不同的数据集的解析不同,可以构建不同的数据集模块和以及可能的数据处理模块(如数据增强);
  • 网络模块,可以拆分成不同类型的网络等

可想而知,模块和模块之间是存在引用的关系,设计时要尽可能做到松耦合,能更友好的变更,如果一次变更需要修改大部分的代码,可以考虑下是否做到合理的模块化设计。

总结一下

  • 模块是功能的划分,是软件程序的架构设计
  • 模块化是减少bug的有效途径
  • 可以适当的模块化,也不要过度模块化,看功能的复杂性,越复杂就有必要拆分的更细
  • 千万不要把所有代码都写到一个文件哦!
  • 模块不要相互引用
  • 如果你听到别人说什么数据层,业务层,xx层,你可以理解为就是模块

2. python中模块

python中模块可以分为2个:

  • 一个python的.py文件,真正的处理功能的模块,可以是公共变量、函数以及类等
  • 对模块的逻辑划分即,通过目录层级的方式来管理模块,python是通过package包的方式来实现的;

一个简单的python模块设计:包括主程序main.py,模块model和两个package包(data/utils)

./
├── main.py
├── model.py
├── data
│   ├── dataset.py
│   ├── __init__.py
├── utils
│   ├── utils.py
│   ├── __init__.py

我们先来看下,和主程序平级的模块的调用,model.py 如下包括变量、函数和类等:

  • model.py

    test = 1
    
    def func():
        print('this is func in model.py')
        
    class Cls(object):
        def __init__(self, a):
            print('init {}'.format(a))
            self.a = a
        
        def process_a(self):
            return self.a + 1
  • 调用

    import model
    print(model.test)
    model.func()
    cls = model.Cls(1)
    print(cls.process_a())
    
    # 1
    # this is func in model.py
    # init 1
    # 2

从上可知,模块是通过import进行导入, 并通过模块名+.的方式调用;

import可以有不同的方式:

  • 导入整个模块: import model
  • 导入模块内的元素: import model.func as func
  • 通过from 方式: from model import func

不过,强烈建议按导入整个模块的方式,避免多个模块相互冲突;比如模块A和模块B都要func,如果通过from方式导入,最终func混淆,实际为后导入的func的功能,除非你又进行as重命名

接着,我们来看下包里模块的调用;我们知道包是同步目录的方式来管理模块,那如何区分目录和包?

是的,python是通过目录下添加__init__.py文件(可以是空的),来使得正常目录变成包。

import data.dataset as dataset
print(dataset.test)
dataset.data_func()
cls = dataset.DCls(1)
print(cls.process_a())

包下模块的调用,在import时需要带上包名,其他和正常的包一样。

包中模块的导入和目录路径一样,可以分为相对导入和绝对导入

  • data.dataset是绝对导入
  • from ..data import dataset as dataset 是相对导入(比如在utils中引用dataset), .表示当前路径,..表示上一级目录,一次类推

不建议相对导入

2.1 python如何寻找模块

我们一般是通过pip install方式来安装第三方的包,安装完在程序里直接通过import就可以直接调用模块的功能,而这些包和模块并不是我们的程序的同级目录,一个问题是python 解释器是如何正确找到这些包和模块?

python解释器搜索模块范围和优先级如下:

  • 1.当前目录
  • 2.PYTHONPATH环境变量目录
  • 3.安装Python时配置的与安装相关的目录

安装第三方的包是属于第3种的情况下,一般是你的python目录或者虚拟环境目录。

所以说自己建立的模块名不要和第三方模块相同,否则你import的时候按照顺序你导入时自己的模块,而不是第三方的模块。了解了这个可以避免自己都觉得不可解释的问题。

对于模块,我们经常会遇到模块找不到的问题: ModuleNotFoundError: No module named 'data.dataseta'
可以检查下:

    1. 模块的包和模块名是否正确
    1. 如果1正确情况,python是否能够搜索到模块,可以通过查看sys.path看下是否包含你需要的模块

以下为本地的python包搜索范围:

['',
 'D:\\Programs\\anaconda3\\python36.zip',
 'D:\\Programs\\anaconda3\\DLLs',
 'D:\\Programs\\anaconda3\\lib',
 'D:\\Programs\\anaconda3',
 'D:\\Programs\\anaconda3\\lib\\site-packages',
 'D:\\Programs\\anaconda3\\lib\\site-packages\\win32',
 'D:\\Programs\\anaconda3\\lib\\site-packages\\win32\\lib',
 'D:\\Programs\\anaconda3\\lib\\site-packages\\Pythonwin',
 'D:\\Programs\\anaconda3\\lib\\site-packages\\IPython\\extensions']

如果sys.path没有包含,可以手动添加的方式将目录添加到sys.path中,如:


import os, sys

cur_path = os.path.abspath(os.path.dirname(__file__))
sys.path.append(cur_path)

当前你可以直接修改PYTHONPATH环境量,linux中为export PYTHONPATH="./"

3. 模块内置方法

python为每个模块提供了内置方法,如果遇到无法解释的现象可以看看这些方法,判断是否调用了正确的模块

  • file 提供__file__ 获取模块路径
  • name 模块名
  • package 包名
  • dir()内置函数返回包含模块定义的名称的字符串的排序
print(model.__file__)
print(dataset.__package__)
print(model.__name__)
print(dir(model))
# D:\mywork\notebook\model.py
# data
# model
# ['Cls', '__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', 'func', 'test']
目录
相关文章
|
4天前
|
Python
【Python进阶(五)】——模块搜索及工作目录
【Python进阶(五)】——模块搜索及工作目录
|
4天前
|
机器学习/深度学习 存储 Python
|
2天前
|
Python
【Python3 查询手册学习】,完整版PDF开放下载_python速查手册·模块卷(全彩版) pdf(1)
【Python3 查询手册学习】,完整版PDF开放下载_python速查手册·模块卷(全彩版) pdf(1)
|
3天前
|
Python
Python使用typing模块(从Python 3.5开始)
【5月更文挑战第10天】Python使用typing模块(从Python 3.5开始)
13 3
|
4天前
|
Python
在Python中,利用`os模块`的`path.exists()`函数可判断文件是否存
【5月更文挑战第12天】在Python中,利用`os模块`的`path.exists()`函数可判断文件是否存在,该函数对路径进行检查,存在则返回True,不存在则返回False。示例代码展示了如何检查'example.txt'文件是否存在并相应打印消息。此外,`os.path.isfile()`用于确认路径是否为文件,仅当是文件时返回True,否则返回False,同样配以示例说明其用法。
23 2
|
4天前
|
Python Windows
python中的异常与模块
python中的异常与模块
12 1
|
4天前
|
JSON 数据格式 Python
Python标准库中包含了json模块,可以帮助你轻松处理JSON数据
【4月更文挑战第30天】Python的json模块简化了JSON数据与Python对象之间的转换。使用`json.dumps()`可将字典转为JSON字符串,如`{"name": "John", "age": 30, "city": "New York"}`,而`json.loads()`则能将JSON字符串转回字典。通过`json.load()`从文件读取JSON数据,`json.dump()`则用于将数据写入文件。
18 1
|
4天前
|
Python
Python实现压缩解压---tarfile模块详解
Python实现压缩解压---tarfile模块详解
|
4天前
|
Linux Python Windows
Python中time和datetime模块详解
Python中time和datetime模块详解
|
4天前
|
存储 Linux 数据安全/隐私保护
python的压缩模块zipfile详解
python的压缩模块zipfile详解