开始一个新的Python项目时,很容易直接投入并开始编码。事实上,花一点时间选择一个优秀的库将在未来的开发中节省大量时间,并带来更愉快的编码体验。在一个理想的世界里,所有的开发者关系都是相互依赖和联系的(协同开发),代码格式完美,没有低级错误,测试覆盖所有代码。另外,所有这些都将在每次提交时得到保证。(统一代码风格、类型检测、高测试覆盖率、自动检测)在这篇文章中,我将介绍如何构建一个可以做到这几点的项目。您可以按照这些步骤操作,或者直接跳到使用cookiecutter生成项目部分(老手)。首先我们新建一个工程目录:mkdirbest_practicescdbest_practicespipx安装Python第三方库的命令行工具Pipx[2]是一个可以用来快速安装Python第三方库的命令行工具。我们将使用它来安装pipenv和cookiecutter。使用以下命令安装pipx:python3-mpipinstall--userpipxpython3-mpipxensurepath使用pipenv进行依赖管理Pipenv[3]自动为您的项目创建和管理virtualenv(虚拟环境),并在安装/卸载包时从Pipfile添加/删除包。它还会生成非常重要的Pipfile.lock以确保可靠性。知道您和您的队友使用相同的库版本会大大增加编程的信心和乐趣。Pipenv解决了使用同一个库不同版本的问题。Pipenv在过去的一段时间里得到了广泛的关注和认可,大家可以放心使用。安装命令如下:pipxinstallpipenv使用black和isort进行代码格式化black[4]可以格式化我们的代码:Black是一个不折不扣的Python代码格式化库。通过使用它,您可以放弃手动格式化代码的细节。作为回报,Black带来了速度、确定性和调整Python代码风格的痛苦,让您可以专注于更重要的事情。无论您正在阅读哪种项目,黑色格式的代码看起来都是一样的。一段时间后,格式不再是问题,因此您可以更专注于内容。黑色通过减少代码的方差使代码检查更快。而isort[5]对我们的导入部分进行排序:isort对您导入的Python包部分(导入)进行排序,因此您不必手动对导入进行排序。它可以按字母顺序对导入进行排序,并自动将它们分成几部分。使用pipenv安装它,这样它们就不会弄乱部署(可以指定只在开发环境中安装):pipenvinstallblackisort--devBlack和isort是不兼容的默认选项,所以我们会让isort遵循黑色的原则。创建一个setup.cfg文件,添加如下配置:[isort]multi_line_output=3include_trailing_comma=Trueforce_grid_wrap=0use_parentheses=Trueline_length=88我们可以通过以下命令运行这些工具:pipenvrunblackpipenvrunisort使用flake8确保代码风格Flake8确保代码遵循PEP8代码规范中定义的标准Python。使用pipenv安装:pipenvinstallflake8--dev与isort一样,它需要一些配置才能很好地与black配合使用。将这些配置添加到setup.cfg:[flake8]ignore=E203,E266,E501,W503max-line-length=88max-complexity=18select=B,C,E,F,W,T4现在我们可以运行flake8,命令:pipenv运行flake8。使用mypy进行静态类型检查Mypy[6]是一个可选的Python静态类型检查器,旨在结合动态(或“鸭子”)类型和静态类型的优点。Mypy将Python的表现力和便利性与强大类型系统的编译时类型检查相结合,在任何PythonVM上运行它们,基本上没有运行时开销。在Python中使用类型需要一点时间来适应,但好处是巨大的。如下:StatictypingcanmakeprogramseasiertounderstandandmaintainStatictypingcanhelpyouearlyfindbugsandspendlesstimetestinganddebugsStatictypingcanhelpyoufindhard-to-findbugsbeforeyourcodegoesintoproductionpipenvinstallmypy--dev默认情况下,Mypy会递归检查所有导入包的类型注解,当库不包含这些注解时会报错。我们需要将mypy配置为仅在我们的代码上运行,并忽略没有类型注释的导入错误。我们假设我们的代码位于以下配置的best_practices包中。将此添加到setup.cfg:[mypy]files=best_practices,testignore_missing_imports=true现在我们可以运行mypy:pipenvrunmypy这是一个有用的备忘单[7]。使用pytest和pytest-cov进行测试使用pytest[8]编写测试非常容易,消除编写测试的摩擦意味着可以快速编写更多测试!pipenvinstallpytestpytest-cov--dev这是来自pytest网站的一个简单示例:#contentoftest_sample.pydefinc(x):returnx+1deftest_answer():assertinc(3)==5执行它:$pipenvrunpytest=============================testsessionstarts===============================platformlinux--Python3.x.y,pytest-5.x.y,py-1.x.y,pluggy-0.x.ycachedir:$PYTHON_PREFIX/.pytest_cacherootdir:$REGENDOC_TMPDIRcollected1itemtest_sample.pyF[100%]===================================失败===================================______________________________________________________________________________________________________________________________deftest_answer():>assertinc(3)==5Eassert4==5E+where4=inc(3)test_sample.py:6:AssertionError==========================1failedin0.12seconds============================我们所有的测试代码都放在测试目录中,所以如果您还想查看测试覆盖率,请将此目录添加到setup.cfg:[tool:pytest]testpaths=test。创建一个新文件.coveragerc指定仅返回我们项目代码的覆盖率统计信息。比方说的best_practices项目,设置如下:[run]source=best_practices[report]exclude_lines=#Havetore-enablethestandardpragmapragma:nocover#Don'tcomplainaboutmissingdebug-onlycode:def__repr__ifself\.debug#Don'tcomplainiftestsdon'thitdefensiveErrorNotcomplain'raiseIssertioncode:raiseIsrunnablecodeisn'trun:if0:if__name__==.__main__.:现在,我们可以运行测试并查看覆盖率。pipenvrunpytest--cov--cov-fail-under=100--cov-fail-under=100是设置项目的测试覆盖率,低于100%就认为失败。用于预提交的Git钩子Git钩子允许您在任何时候想要提交或推送时运行脚本。这使我们能够在每次提交/推送时自动运行所有检测和测试。pre-commit[9]使得配置这些钩子变得容易。Git挂钩脚本对于在提交代码审查之前识别简单问题很有用。我们将在每次提交时运行挂钩,以自动指出代码中的问题,例如缺少分号、尾随空格和调试语句。通过在代码审查之前指出这些问题,代码审查者可以专注于更改的代码内容,而不会浪费时间处理这些琐碎的样式问题。在这里,我们将上述所有工具配置为在提交Python代码更改(gitcommit)时执行,然后仅在推送时运行pytest覆盖率(因为测试是最后一步)。使用以下配置创建一个新文件.pre-commit-config.yaml:repos:-repo:localhooks:-id:isortname:isortstages:[commit]language:systementry:pipenvrunisorttypes:[python]-id:blackname:blackstages:[提交]语言:systementry:pipenvrunblacktypes:[python]-id:flake8name:flake8stages:[提交]语言:systementry:pipenvrunflake8types:[python]排除:setup.py-id:mypyname:mypystages:[提交]语言:systementry:pipenvrunmypytypes:[python]pass_filenames:false-id:pytestname:pyteststages:[commit]language:systementry:pipenvrunpytesttypes:[python]-id:pytest-covname:pyteststages:[push]language:systementry:pipenvrunpytest--cov--cov-fail-under=100types:[python]pass_filenames:false如果你需要跳过这些钩子,你可以运行gitcommit--no-verify或gitpush--no-verify使用cookiecutter来生成项目现在,我们已经知道了理想的项目包含什么,我们可以将其转换为模板[10],以便可以使用单个命令生成包含这些的新项目librariesandconfiguration:pipxrunco??okiecuttergh:sourcery-ai/python-best-practices-cookiecutter填写项目名称和仓库名称,会为你生成一个新项目。要完成设置,请执行以下步骤:#Enterprojectdirectorycd
