Python的工程化之路

在工程化上,Python相比于Java,C#这类语言还是差了不少,不过整个生态还是不错的.

项目结构

一般有两种,一种称为flat另一种为src.

  1. ├── sample
    │ ├── AUTHORS.rst
    │ ├── docs
    | | ├── conf.py
    │ │ └── index.rst
    │ ├── HISTORY.rst
    │ ├── LICENSE
    │ ├── makefile
    │ ├── MANIFEST.in
    │ ├── README.rst
    │ ├── requirements.txt
    │ ├── sample
    | | ├── app.py
    │ │ └── helper.py
    | ├── setup.cfg
    | ├── setup.py
    │ └── tests
    image-20231204170021714

  1. image-20231204171740258

主要是使用poetry等工具打包的时候需要注意一下,因为pyproject.toml字段不完全相同.

FAQ

  1. ImportError: attempted relative import with no known parent package

包中的模块使用相对导入时不能直接运行该模块,一般是其他包或顶级模块进行调用

工具链

版本管理工具

Anaconda可以同时解决Python版本和包管理的问题,但如果只是想开发个包,没有必要使用conda,在linux上可以考虑pyenv+poetry,windows上有对应的pyenv-windows+poetry.

pyenv允许您轻松地在多个版本的Python之间切换。它简单、不引人注目,并且遵循了UNIX传统的单用途工具,可以很好地完成一件事。

pyenv/pyenv: Simple Python version management (github.com)

包管理工具

目前开发Python包我推荐Poetry或者PDM,如果是搞数据计算直接Anaconda.

Poetry

Introduction | Documentation | Poetry - Python dependency management and packaging made easy (python-poetry.org)

某种程度上告别setup.py,除了一般的虚拟环境和包管理之外,打包和发布到PYPI等都支持,也是现在比较火的工具.

虚拟环境管理类似conda,会在某个目录下放所有的虚拟环境

image-20231204163324338

1
2
3
poetry init
poetry install
poetry shell

通过初始化一个新的Poetry项目,这将以交互方式生成一个文件pyproject.toml。该文件将具有所有包依赖项。这与requirements.txt文件类似。

当参数 virtualenvs.createtrue 时,执行 poetry installpoetry add 时会检测当前项目是否有虚拟环境,没有就自动创建,默认为 true

当参数 virtualenvs.in-projecttrue 时,虚拟环境的依赖将会放置于项目的文件夹内,而不是 poetry 默认的 {cache-dir}/virtualenvs,默认为 false

我的配置如下:

image-20231204164441421

当Poetry完成安装后,它会将所有包及其下载的确切版本写入Poetry.lock文件,从而将项目锁定到这些特定版本。该锁定文件也应包含在您的项目repo中,以便在项目中工作的每个人都被锁定到相同版本的依赖项。

image-20231204163627134

PDM

pdm-project/pdm: A modern Python package and dependency manager supporting the latest PEP standards (github.com)

支持最新PEP标准的现代Python包和依赖项管理器. Poetry的pyproject.toml与PEP标准不完全符合.

PDM可以管理项目和集中位置的虚拟环境(venv),类似于Pipenv。它从标准化的pyproject.toml文件中读取项目元数据,并支持锁定文件。用户可以通过插件添加额外的功能,这些功能可以通过将其作为分发版上传来共享。与Poetry和Hatch不同,PDM不局限于特定的构建后端;用户可以自由选择他们喜欢的任何构建后端。

Formatter

代码格式化工具,一般用black就够了.

Black

Black是不折不扣的Python代码格式化程序。通过使用它,您同意放弃对手工格式化细节的控制。作为回报,Black为您提供了速度、决定论和自由,使您免受pycode风格对格式的唠叨。你会为更重要的事情节省时间和精力。无论您正在阅读的项目是什么,变黑的代码看起来都是一样的。一段时间后,格式将变得透明,您可以转而关注内容。Black通过产生尽可能小的差异来加快代码审查。

1
2
pip install black
black {source_file_or_directory}

yapf

YAPF是一个基于clang格式的Python格式化程序(由Daniel Jasper开发)。本质上,该算法采用代码并计算符合配置样式的最佳格式。它省去了维护代码的许多繁琐工作。最终目标是YAPF生成的代码与程序员在遵循样式指南的情况下编写的代码一样好。

1
pip install yapf

autopep8

autoep8自动格式化Python代码,以符合PEP8样式指南。它使用pycodestyle实用程序来确定需要格式化代码的哪些部分。autoep8能够修复pycodestyle可能报告的大多数格式问题。

1
2
pip install --upgrade autopep8
autopep8 --in-place --aggressive --aggressive <filename>

Linter

一般用pylint足矣,喜欢尝鲜的可以用用Ruff.

PyLint

Pylint是Python 2或3的静态代码分析器。最新版本支持Python 3.8.0及以上版本。Pylint在不实际运行代码的情况下分析代码。它检查错误,强制执行编码标准,寻找代码气味,并可以就如何重构代码提出建议。

1
pip install pylint

flake8

Flake8是这些工具的包装:PyFlakespycode样式Ned Batchelder的McCabe脚本Flake8通过启动单个Flake8命令来运行所有工具。它在每个文件的合并输出中显示警告。PyCQA/flake8: flake8 is a python tool that glues together pycodestyle, pyflakes, mccabe, and third-party plugins to check the style and quality of some python code. (github.com)

Ruff

比较新的工具astral-sh/ruff: An extremely fast Python linter and code formatter, written in Rust. (github.com),不只是语法提示器,也可以用于格式化.

1
2
3
4
5
pip install ruff

ruff path/to/code/to/check.py
ruff path/to/code/
ruff path/to/code/*.py

类型检查工具

在Python中使用typing的检查工具,此外与PydanticWelcome to Pydantic - Pydantic搭配使用效果更佳

Pydantic是Python中使用最广泛的数据验证库。Pydantic快速且可扩展,可以很好地处理您的linters/IDE/brain。

定义数据应该如何使用纯规范的Python 3.7+;用Pydantic验证它。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
from datetime import datetime
from typing import Tuple

from pydantic import BaseModel


class Delivery(BaseModel):
timestamp: datetime
dimensions: Tuple[int, int]


m = Delivery(timestamp='2020-01-02T03:04:05Z', dimensions=['10', '20'])
print(repr(m.timestamp))
#> datetime.datetime(2020, 1, 2, 3, 4, 5, tzinfo=TzInfo(UTC))
print(m.dimensions)
#> (10, 20)

Mypy

python/mypy: Optional static typing for Python (github.com)

Mypy是Python的静态类型检查器。类型检查器有助于确保您在代码中正确使用变量和函数。

使用mypy,将类型提示(PEP484)添加到Python程序中,当您错误地使用这些类型时,mypy会发出警告。Python是一种动态语言,所以通常只有当你试图运行它时,你才会在代码中看到错误。Mypy是一个静态检查器,所以它甚至不用运行就可以发现程序中的错误!

1
2
python3 -m pip install -U mypy
mypy PROGRAM

Pyright

microsoft/pyright: Static Type Checker for Python (github.com)

Pyright是一个功能齐全、基于标准的Python静态类型检查器。它是为高性能而设计的,可以与大型Python源代码库一起使用。

Git pre-commit hook

git commit之前设置hook进行代码检查

Test

测试工具

Pytest

pytest框架使编写小型可读测试变得容易,并且可以扩展以支持应用程序和库的复杂功能测试。

1
pip install -U pytest

参考资料

  1. python项目结构示例(python代码结构、python目录结构)与python部署结构、python部署目录、flask项目结构、flask目录_python项目结构目录结构-CSDN博客
  2. 各类Python项目的项目结构及代码组织最佳实践python项目结构__弯弓__的博客-CSDN博客
  3. Python最佳工程实践,建立一个完美的工程项目 - cuiyubo - 博客园 (cnblogs.com)
  4. 8 Pre-commit Git Hooks You Must Know for Improved Productivity - Hatica
  5. 结构化您的工程 — The Hitchhiker’s Guide to Python (pythonguidecn.readthedocs.io)
-------------本文结束感谢您的阅读-------------
感谢阅读.

欢迎关注我的其它发布渠道