当开始一个新的 Python 我的项目时,大家很容易一头扎进去就开始编码。其实花一点工夫抉择优良的库,将为当前的开发节俭大量工夫,并带来更高兴的编码体验。
在现实世界中,所有开发人员的关系是相互依赖和关联的(合作开发),代码要有完满的格局、没有低级的谬误、并且测试笼罩了所有代码。另外,所有这些将在每次提交时都能够失去保障。(代码格调对立、类型检测、测试覆盖率高、自动检测)
在本文中,我将介绍如何建设一个能够做到这些点的我的项目。您能够依照步骤操作,也能够间接跳到 应用 cookiecutter 生成我的项目 局部(新手)。
首先,让咱们创立一个新的我的项目目录:
mkdir best_practices
cd best_practices
pipx 装置 Python 三方库的命令行工具
Pipx[2] 是一个可用于疾速装置 Python 三方库的命令行工具。咱们将应用它来装置 pipenv 和 cookiecutter。通过上面的命令装置 pipx:
python3 -m pip install --user pipx
python3 -m pipx ensurepath
应用 pipenv 进行依赖治理
Pipenv[3] 为您的我的项目主动创立和治理 virtualenv(虚拟环境),并在装置 / 卸载软件包时从 Pipfile 增加 / 删除软件包。它还会生成十分重要的 Pipfile.lock 用于保障依赖的可靠性。
当你晓得,你和你的队友正在应用雷同的库版本时,这将会极大地提高编程的信念和乐趣。Pipenv 很好地解决了应用雷同的库,版本不同的这一问题,Pipenv 在过来的一段时间里取得了宽泛的关注和认可,你能够放心使用。装置命令如下:
pipx install pipenv
应用 black 和 isort 进行代码格式化
black[4] 能够格式化咱们的代码:
Black 是毫不妥协的 Python 代码格式化库。通过应用它,你将放弃手动调整代码格局的细节。作为回报,Black 能够带来速度、确定性和防止调整 Python 代码格调的懊恼,从而有更多的精力和工夫放在更重要的事件上。
无论你正在浏览什么样的我的项目,用 black 格式化过的代码看起来都差不多。一段时间后格局不再是问题,这样你就能够更专一于内容。
black 通过缩小代码的差异性,使代码查看更快。
而 isort[5] 是对咱们的 imports 局部进行排序:
isort 为您导入的 Python 包局部(imports)进行排序,因而你不用再对 imports 进行手动排序。它能够按字母程序对导入进行排序,并主动将其拆分成多个局部。
应用 pipenv 装置它,以便它们不会使部署凌乱(能够指定只在开发环境装置):
pipenv install black isort --dev
Black 和 isort 并不兼容的默认选项,因而咱们将让 isort 遵循 black 的准则。创立一个 setup.cfg 文件并增加以下配置:
[isort]
multi_line_output=3
include_trailing_comma=True
force_grid_wrap=0
use_parentheses=True
line_length=88
咱们能够应用以下命令运行这些工具:
pipenv run black
pipenv run isort
应用 flake8 保障代码格调
Flake8 确保代码遵循 PEP8 中定义的规范 Python 代码标准。应用 pipenv 装置:
pipenv install flake8 --dev
就像 isort 一样,它须要一些配置能力很好地与 black 配合应用。将这些配置增加到 setup.cfg:
[flake8]
ignore = E203, E266, E501, W503
max-line-length = 88
max-complexity = 18
select = B,C,E,F,W,T4
当初咱们能够运行 flake8 了,命令:pipenv run flake8。
应用 mypy 进行动态类型查看
Mypy[6] 是 Python 的非强制的动态类型查看器,旨在联合动静(或“鸭子”)类型和动态类型的长处。Mypy 将 Python 的表达能力和便利性与功能强大的类型零碎的编译时类型查看联合在一起,应用任何 Python VM 运行它们,基本上没有运行时开销。
在 Python 中应用类型须要一点工夫来适应,然而益处却是微小的。如下:
- 动态类型能够使程序更易于了解和保护
- 动态类型能够帮忙您更早地发现错误,并缩小测试和调试的工夫
- 动态类型能够帮忙您在代码投入生产之前发现难以发现的谬误
pipenv install mypy --dev
默认状况下,Mypy 将递归查看所有导入包的类型正文,当库不蕴含这些正文时,就会报错。咱们须要将 mypy 配置为仅在咱们的代码上运行,并疏忽没有类型正文的导入谬误。咱们假如咱们的代码位于以下配置的 best_practices 包中。将此增加到 setup.cfg:
[mypy]
files=best_practices,test
ignore_missing_imports=true
当初咱们能够运行 mypy 了:
pipenv run mypy
这是一个有用的 备忘单[7]。
用 pytest 和 pytest-cov 进行测试
应用 pytest[8] 编写测试非常容易,打消编写测试的阻力意味着能够疾速的编写更多的测试!
pipenv install pytest pytest-cov --dev
这是 pytest 网站上的一个简略示例:
# content of test_sample.py
def inc(x):
return x + 1
def test_answer():
assert inc(3) == 5
要执行它:
$ pipenv run pytest
=========================== test session starts ============================
platform linux -- Python 3.x.y, pytest-5.x.y, py-1.x.y, pluggy-0.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 inc(3) == 5
E assert 4 == 5
E + where 4 = inc(3)
test_sample.py:6: AssertionError
========================= 1 failed in 0.12 seconds =========================
咱们所有的测试代码都放在 test 目录中,因而请将此目录增加到 setup.cfg:
[tool:pytest]
testpaths=test
如果还想查看测试覆盖率。创立一个新文件 .coveragerc,指定只返回咱们的我的项目代码的覆盖率统计信息。比方示例的 best_practices 我的项目,设置如下:
[run]
source = best_practices
[report]
exclude_lines =
# Have to re-enable the standard pragma
pragma: no cover
# Don't complain about missing debug-only code:
def __repr__
if self\.debug
# Don't complain if tests don't hit defensive assertion code:
raise AssertionError
raise NotImplementedError
# Don't complain if non-runnable code isn't run:
if 0:
if __name__ == .__main__.:
当初,咱们就能够运行测试并查看覆盖率了。
pipenv run pytest --cov --cov-fail-under=100
–cov-fail-under=100 是设定我的项目的测试覆盖率如果小于 100% 那将认定为失败。
pre-commit 的 Git hooks
Git hooks 可让您在想要提交或推送时随时运行脚本。这使咱们可能在每次提交 / 推送时,主动运行所有检测和测试。pre-commit[9] 可轻松配置这些 hooks。
Git hook 脚本对于在提交代码审查之前,辨认简略问题很有用。咱们在每次提交时都将运行 hooks,以主动指出代码中的问题,例如短少分号、尾随空白和调试语句。通过在 code review 之前指出这些问题,代码审查者能够专一于变更的代码内容,而不会浪费时间解决这些琐碎的款式问题。
在这里,咱们将上述所有工具配置为在提交 Python 代码改变时执行(git commit),而后仅在推送时运行 pytest coverage(因为测试要在最初一步)。创立一个新文件 .pre-commit-config.yaml,配置如下:
repos:
- repo: local
hooks:
- id: isort
name: isort
stages: [commit]
language: system
entry: pipenv run isort
types:
- id: black
name: black
stages: [commit]
language: system
entry: pipenv run black
types:
- id: flake8
name: flake8
stages: [commit]
language: system
entry: pipenv run flake8
types:
exclude: setup.py
- id: mypy
name: mypy
stages: [commit]
language: system
entry: pipenv run mypy
types:
pass_filenames: false
- id: pytest
name: pytest
stages: [commit]
language: system
entry: pipenv run pytest
types:
- id: pytest-cov
name: pytest
stages: [push]
language: system
entry: pipenv run pytest --cov --cov-fail-under=100
types:
pass_filenames: false
如果须要跳过这些 hooks,能够运行 git commit –no-verify 或 git push –no-verify
应用 cookiecutter 生成我的项目
当初,咱们曾经晓得了现实我的项目中蕴含了什么,咱们能够将其转换为 模板[10] 从而能够应用单个命令生成一个蕴含这些库和配置的新我的项目:
pipx run cookiecutter gh:sourcery-ai/python-best-practices-cookiecutter
填写项目名称和仓库名称,将为您生成新的我的项目。
要实现设置,请执行下列步骤:
# Enter project directory
cd <repo_name>
# Initialise git repo
git init
# Install dependencies
pipenv install --dev
# Setup pre-commit and pre-push hooks
pipenv run pre-commit install -t pre-commit
pipenv run pre-commit install -t pre-push
模板我的项目蕴含一个非常简单的 Python 文件和测试,能够试用下面这些工具。在编写完代码感觉没问题后,就能够执行第一次 git commit,所有的 hooks 都将运行。
集成到编辑器
尽管在提交时晓得我的项目的代码始终保持最高水准是件令人兴奋的事件。但如果在代码已全副批改实现之后(提交时),再发现有问题还是会让人很不爽。所以,实时暴露出问题要好得多。
在保留文件时,花一些工夫确保代码编辑器运行这些命令。有及时的反馈,这意味着你能够在代码还有印象的时候能迅速解决引入的任何小问题。
我集体应用一些杰出的 Vim 插件来实现此工作:
- ale[11] 实时运行 flake8 并在保留文件时运行 black、isort 和 mypy
- 与 projectionist 集成的[12] vim-test[13] 在文件保留上运行 pytest
以上就是本次分享的所有内容,想要理解更多 python 常识欢送返回公众号:Python 编程学习圈,发送“J”即可收费获取,每日干货分享