7.使用工具辅助开发

1 建议 70:从 PyPI 安装包

PyPI 全称 Python Package Index,直译过来就是“Python 包索引”,它是 Python 编程语言的软件仓库,可以通过包的名字查找、下载、安装 PyPI 上的包。

setuptools 是来自 PEAK(Python Enterprise Application Kit,一个致力于提供 Python 开发企业级应用工具包的项目),由一组发布工具组成,方便程序员下载、构建、安装、升级和卸载 Python 包,它可以自动处理包的依赖关系。

setuptools安装之后,就拥有了叫做 easy_install 的第三方管理工具,不过easy_install 在2008年被pip替代,现在已被弃用。

本人常用PyPI国内镜像:清华源

2 建议 71:使用 pip 和 yolk 安装、管理包

目前官方推荐的包管理器是pip,从 Python 3.4 开始 pip 就和 Python 捆绑在一起了。

pip install requests # 默认安装最新版本
pip install requests==2.6.0 # 可指定版本
pip install --upgrade requests # 更新到最新版本
pip show requests # 查看特定包的信息
pip list # 列出所有安装包
pip install -r requirements.txt # 批量安装

进一步了解可通过pip -help查看或参阅pip官方文档

yolk模块也是一个包管理器,Yolk3k模块增加了对Python3的支持,yolk1977则在Yolk3k模块基础上进行了维护和更新,具体可参考yolk1977文档

3 建议 72:做 paster 创建包

时过境迁,distutils模块已被弃用并计划在 Python 3.12 中移除,而<code>pastescript</code>项目目前只是保持着最基本的维护,不再深入研究,本小节仅对几个创建包相关的概念进行简单说明:

  • distutils模块是Python 官方早期开发的一个分发打包工具,精髓在于编写 setup.py
  • 官方用setuptools模块替代了distutils,实现了Python 包更好的创建和分发
  • Python 包的分发主要为两种:源码包(压缩包)和二进制包(.whl文件)
  • 打包分发最关键的一步是编写 setup.py 文件
from setuptools import setup

setup(
    name='mypackage',
    version='0.0.1',
    packages=['mypackage'],
    install_requires=[
        'requests',
        'importlib; python_version == "2.6"',
    ],
)

除此之外,还可以添加作者信息、程序分类信息、环境的限制说明、授权方式等等

setup 函数常用的一些参数:

pbr模块是 setuptools 的辅助工具,可以用于更高效的打包

setup 函数参数参考 pbr模块官方文档

本小节部分内容参考自知乎-花了两天,终于把 Python 的 setup.py 给整明白了

4 建议 73:理解单元测试概念

优质单元测试的好处:

  • 减少潜在 bug
  • 缩减软件修复的成本
  • 为集成测试提供基本保障

单元测试步骤:

  • 创建测试计划(Test Plan)
  • 编写测试用例,准备测试数据
  • 编写测试脚本
  • 编写被测代码,在代码完成之后执行测试脚本
  • 修正代码缺陷,重新测试直到代码可接受为止

单元测试基本原则:

  • 一致性
  • 原子性
  • 单一职责:测试应该基于情景(scenario)和行为,而不是方法。如果一个方法对应着多种行为,应该有多个测试用例;而一个行为即使对应多个方法也只能有一个测试用例
  • 隔离性:不能依赖于具体的环境设置,如数据库的访问、环境变量的设置、系统的时间等;也不能依赖于其他的测试用例以及测试执行的顺序,并且无条件逻辑依赖。单元测试的所有输入应该是确定的,方法的行为和结构应是可以预测的。

unittest模块提供了一系列创建和运行测试的工具,具体可参考unittest模块--单元测试框架

5 建议 74:为包编写单元测试

目前书中所提及的nose模块已经基本维护状态,文档明确推荐使用nose2模块或者pytest模块。nose2模块作为unittest模块的拓展,不完全集成nose模块的所有特性,文档也推荐使用pytest模块。综上,本人也推荐pytest模块:

pytest模块作为第三方单元测试框架,提供轻量化的语法来编写测试,简单示例如下:

def func(x):
    return x + 1

def test_answer():
    assert func(3) == 5

测试结果如下:

$ pytest
=========================== test session starts ============================
platform linux -- Python 3.x.y, pytest-6.x.y, py-1.x.y, pluggy-1.x.y
cachedir: $PYTHON_PREFIX/.pytest_cache
rootdir: $REGENDOC_TMPDIR
collected 1 item

test_sample.py F                                                     [100%]

================================= FAILURES =================================
_______________________________ test_answer ________________________________

    def test_answer():
>       assert func(3) == 5
E       assert 4 == 5
E        +  where 4 = func(3)

test_sample.py:6: AssertionError
========================= short test summary info ==========================
FAILED test_sample.py::test_answer - assert 4 == 5
============================ 1 failed in 0.12s =============================

nose2项目地址

pytest官方文档

6 建议 75:利用测试驱动开发提高代码的可测性

测试驱动开发(Test Driven Development,TDD)是敏捷开发中一个非常重要的理念,它提倡在真正开始编码之前测试先行,先编写测试代码,再在其基础上通过基本迭代完成编码,并不断完善。

7 建议 76:使用 Pylint 检查代码风格

Pylint是一个检查Python代码错误的工具,其他类似的项目包括pychecker(现在已经失效)、pyflakesflake8myypy。Pylint使用的默认编码风格遵循PEP 8标准。

Pylint的主要作用:

  • 代码风格审查。以 Guido van Rossum 的 PEP8 为标准

  • 代码错误检查。如未被实现的接口,方法缺少对应参数,访问模块中未定义的变量等

  • 发现重复以及设计不合理的代码,帮助重构

  • 高度的可配置化和可定制化,通过 pylintrc 文件的修改可以定义自己适合的规范

  • 支持各种 IDE 和编辑器集成。如 Emacs、Eclipse、WingIDE、VIM、Spyder 等

  • 能够基于 Python 代码生成 UML 图

  • 能够与 Hudson、Jenkins 等持续集成工具相结合支持自动代码审查

使用 Pylint 分析代码,输出分为两部分:一部分为源代码分析结果,第二部分为统计报告

源代码分析主要以消息的形式显示代码中存在的问题,消息以 MESSAGE_TYPE:LINE_NUM:[OBJECT:]MESSAGE 的形式输出,主要分为以下 5 类:

  • (C)惯例,违反了编码风格标准

  • (R)重构,写得非常糟糕的代码

  • (W)警告,某些 Python 特定的问题

  • (E)错误,很可能是代码中的 bug

  • (F)致命错误,阻止 Pylint 进一步运行的错误

报告部分主要是一些统计信息,总体来说有以下6 类:

  • Statistics by type:检查的模块、函数、类等数量,以及存在文档注释以及不良命名的比例

  • Raw metrics:代码、注释、文档、空行等占模块代码量的百分比统计

  • Duplication:重复代码的统计百分比

  • Messages by category:按照消息类别分类统计的信息以及和上一次运行结果的对比

  • Messages:具体的消息 ID 以及它们出现的次数

  • Global evaluation:根据公式计算出的分数统计:10.0 - ((float(5 * error + warning + refactor + convention) / statement) * 10)

8 建议 77:进行高效的代码审查

  • 以提高代码质量为目的,把代码审查当做一个学习的机会
  • 尽量避免管理层参与,不混杂KPI(Key Performance Indicator) 评价的成分
  • 合理使用技术和工具,控制评审时间和评审内容
  • 关注技术层面,对事不对人;记录问题,追踪进一步行动

9 建议 78:将包发布到 PyPI

setuptools 模块提供了完善的打包、发布的支持:

python setup.py sdist # 根据当前平台创建默认格式的存档
python setup.py sdist --formats=zip, gztar # 指定发布包格式
python setup.py bdist_wininst # 二进制软件包

发布包到 PyPi:

  • 注册账号
  • 创建 ~/.pypirc 文件,配置地址和账号
  • 使用python setup.py register注册项目信息
  • 使用python setup.py upload上传项目的源码包

往年同期文章