Python教程:如何建立完美自动化的Python-starter项目
在开始一个新的Python项目时,很容易就从编码入手.花费少量时间用最好的工具配置项目,将节省大量时间,并带来愉快的编码体验.
在理想的编程环境中,依赖关系对于所有开发人员都是相同的,代码将被完美地格式化,禁止常见错误,并且测试将涵盖所有内容.此外,所有这些都将在每次提交时自动的帮您执行format/check.
在本文中,我将介绍如何设置一个理想编程环境.您可以按照步骤操作,也可以直接跳转到通过安装pipx
和pipenv
自动生成新项目,然后生成新项目.
首先我们创建一个新的项目:
mkdir best_practices
cd best_practices
1. Python命令行工具 pipx
Pipx
是一个简洁有效的实用程序,允许快速安装python命令行工具.我们将用它来安装pipenv
和cookiecutter
.
python3 -m pip install --user pipx
python3 -m pipx ensurepath
2. 使用pipenv进行依赖管理
Pipenv会自动为您的项目创建和管理virtualenv,当您安装/卸载package时,Pipenv自动的从Pipfile安装/卸载package. 它还生成了非常重要的Pipfile.lock.
知道您和您的同事正在使用相同的package版本是一个巨大的信心提升,Pipenv能够确保做到这一点.
pipx install pipenv
3. 使用black和isort进行代码格式化
使用Black格式化代码:
Black是不妥协的Python代码格式化程序.通过使用它,您同意放弃对手动格式化细节的控制. 作为回报,Black为您提供速度,决定论和免于pycodestyle唠叨格式化的自由.您将为更重要的事情节省时间和精力.
无论您正在阅读的项目如何,Blackened代码看起来都是一样的.一段时间后,格式化变得透明,您可以专注于内容.
而isort排序import:
sort您的python import.isort是一个Python实用程序/库,用于按字母顺序对import进行排序,并自动分成多个部分.
让我们使用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
4. 遵循flake8的风格
Flake8确保我们的代码遵循PEP8中定义的标准.使用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
.
5. 使用mypy的静态类型检查器
Mypy是Python的可选静态类型检查器,旨在结合动态类型和静态类型的好处. Mypy将Python的便利性与强大的类型系统和编译时类型检查相结合
在Python中使用类型需要一点点适应,但好处是巨大的
- 静态类型可以使程序更容易理解和维护
- 静态类型可以帮助您更早地发现错误,减少测试和调试
- 静态类型可以帮助您在代码投入生产之前找到难以发现的错误
pipenv install mypy --dev
默认情况下,Mypy将递归检查所有类型注释的import,这会导致库不包含这些注释时出错.我们需要将mypy配置为仅在我们的代码上运行, 并忽略没有类型注释的导入的任何错误.我们假设我们的代码存在于best_practices以下配置的包中.将此添加到setup.cfg:
[mypy]
files=best_practices,test
ignore_missing_imports=true
现在我们可以运行mypy:
pipenv run mypy
这里有一个快速查询手册mypy
6. 使用pytest和pytest-cov进行测试
使用pytest编写测试非常容易
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只返回我们的应用程序代码的coverage率统计信息, 我们再次假设我们的应用程序代码存在于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
如果我们对应用程序代码的测试覆盖率低于100%,则会失败.
7. Git挂钩 pre-commit
Git钩子允许您在任何时候提交或推送时运行脚本.这使我们可以在每次提交/推送时自动运行所有的linting和test.pre-commit允许轻松配置这些钩子:
在提交代码审查之前,Git钩子脚本可用于识别简单问题.我们在每次提交时运行我们的钩子,以自动指出代码中的问题,
在这里,我们配置所有上述工具,以便在提交时在任何已更改的python文件上运行,并且仅在推送时运行pytest coverage,因为它可能很慢.
创建一个新文件.pre-commit-config.yaml
:
repos:
- repo: local
hooks:
- id: isort
name: isort
stages: [commit]
language: system
entry: pipenv run isort
types: [python]
- id: black
name: black
stages: [commit]
language: system
entry: pipenv run black
types: [python]
- id: flake8
name: flake8
stages: [commit]
language: system
entry: pipenv run flake8
types: [python]
exclude: setup.py
- id: mypy
name: mypy
stages: [commit]
language: system
entry: pipenv run mypy
types: [python]
pass_filenames: false
- id: pytest
name: pytest
stages: [commit]
language: system
entry: pipenv run pytest
types: [python]
- id: pytest-cov
name: pytest
stages: [push]
language: system
entry: pipenv run pytest --cov --cov-fail-under=100
types: [python]
pass_filenames: false
如果您需要跳过这些钩子,您可以运行git commit --no-verify
或git push --no-verify
8. 使用cookiecutter生成项目
现在我们已经看到了理想项目包含的内容,我们可以将其转换为模板,以使用单个命令生成新项目:
pipx run cookiecutter gh:sourceryai/python-best-practices-cookiecutter
填写项目名称和repo名称,将为您生成项目.
要完成设置,请按照下列步骤操作:
# 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运行所有的git hooks.