- ubuntu12.04环境下使用kvm ioctl接口实现最简单的虚拟机
- Ubuntu 通过无线网络安装Ubuntu Server启动系统后连接无线网络的方法
- 在Ubuntu上搭建网桥的方法
- ubuntu 虚拟机上网方式及相关配置详解
CFSDN坚持开源创造价值,我们致力于搭建一个资源共享平台,让每一个IT人在这里找到属于你的精彩世界.
这篇CFSDN的博客文章使用哪些工具,可以提升 Python 项目质量由作者收集整理,如果你对这篇文章有兴趣,记得点赞哟.
在编写项目时,都会对代码质量有一定的追求, 比如代码艺术、设计模式、 重构设计等等。但是一个良好 Python 项目除了程序员本身的代码质量能力之外, 还有系统设计和代码质量工具等等。不过由于每个系统的设计都会有一些不同, 系统设计需要程序员一定的经验, 需要跟着项目去一起成长.
代码质量工具可以都抽离出来,应用到每个项目中, 本文则是我对这些代码质量工具的简要使用总结.
每个团队或个人, 都必须要有一套自己的分支管理和提交代码规范, 对于分支管理, 一般会选用 git flow , 如果不太会使用, 前期可以使用git flow 备忘清单(https://danielkummer.github.io/git-flow-cheatsheet/index.zh_CN.html), 并且对于 master , develop 等分支设置一些权权限。另外提交的信息也要有对应的规范, 比如本次提交属于哪种类型, 本次提交的功能是什么等等, 但是这个提交规范往往都没有一个标准, 只要团队和个人用的顺心, 能通过这些规范来减少开发矛盾, 复盘代码等等即可。我常使用的是:
其中每个字段代表的含义如下:
issue_id: 代表一个issue的id, 在准备写功能或者修复一个bug时,都应该先提一个issue, 这个issue要详细的写明要修改什么,达到什么目的,然后再针对这个issue提交代码 。
+,-,*
来分别代表增加, 删除, 修改 operating: 代表本次代码变化, 具体有如下几种 。
feat:新功能 。
fix:修复bug 。
doc:文档改变 。
style:代码格式改变 。
refactor:某个已有功能重构 。
perf:性能优化 。
test:增加测试 。
build:改变了build工具 如 grunt换成了 npm 。
revert:撤销上一次的commit 。
info: 简要的说明本次提交信息 。
一个项目最重要的就是跑起来, 而大家基本会同时在本地开发多个项目, 每个项目用到的环境都是不一样的, 所以就需要用到虚拟环境隔离。在Python中提供了一个叫 venv 的虚拟环境管理包,他非常稳定, 同时功能也不是很多, 一般只用在服务器上, 对于本地开发来说, 都会想要更多的功能, 更加方便的对虚拟环境, 依赖包进行管理, Python包管理领域相关工具很多, 包括争议很大的 Pipenv , 我在经过多种尝试后, 觉得 Poetry 比较好用, 坑也比较少.
Poetry(https://python-poetry.org/)官网的简介就是让Python包安装和依赖管理变得容易, 我觉得 Poetry 是最好用的, 他不止对包管理有很多的支持, 还有其他的拓展功能, 如方便的打包和发布, 脚本简写等等.
在第一次大多数的Python项目编写中, 基本上都是按以下流程进行:
1.安装对应的Python版本 。
python -m venv
的方式在项目创建venv的虚拟环境 python -m pip install
的方式安装依赖 python -m pip freeze > requirements.txt
生成依赖文件 而 Poetry 则十分简单, 以下是 poetry 的创建流程:
通过命令 poetry new 就可以创建一个项目手脚架 。
可以看到 Poetry 创建了一个 example 的项目, 生成了对应的文件夹以及包括项目信息的 pyproject.toml 。如果在已有项目, 则通过命令 poetry init 来初始化:
Poetry 默认使用系统默认的Python环境, 不过可以通过 poetry env use 来指定Python版本, 之后就创建了一个虚拟环境了。默认的虚拟环境配置是存放在 /home/{user}/.cache/pypoetry 目录的, 可以直接查看配置了解:
而默认的使用习惯(包括一些第三方包) 都是认为venv是创建在项目路径下的, 同时这也方便管理。 poetry 可以通过如下命令进行更改后再创建虚拟环境,达到在项目路径下创建虚拟环境的效果:
在虚拟环境创建好后可以通过 。
来执行想要运行的命令或者调用Python包, 也可以通过 poetry shell 启动一个被虚拟环境包裹的交互shell. 。
虚拟环境创建好后, 就可以安装依赖了, 可以直接使用 poetry 的 add 命令安装依赖, 其中带有 --dev 表示他是开发环境依赖包(开发环境依赖包和生成环境依赖包区分是很有益的):
安装依赖后可以看到 pyproject.toml 文件发生变动:
文件中多了刚刚安装的 flask 依赖和 pytest 依赖, 且 pytest 依赖是属于dev依赖。在后面还可以通过 poetry 的命令生成对应的生产环境依赖文件 requirement.txt 和测试环境依赖文件 requirements-dev.txt :
这样区分测试环境和生产环境的依赖可以尽量的减少测试需要的依赖包对生成环境造成影响.
除了增加依赖外, poetry 还支持很多种依赖操作方法, 具体如下:
对于一般的自用Python项目来说, 上面的 poetry 操作已经够了, 如果需要发布自己的包到pypi, 或者安装github最新的并未发布的包则可以使用他的其他拓展命令, 具体可以见文档(https://python-poetry.org/docs/)。个人觉得 poetry 已经非常优秀了, 但是由于缺少一个稳定的维护团队, 所以难免有bug, 这时候可以采用降级的方法解决, 比如安装依赖失败, 则可以使用 poetry run pip install 安装包, 再手动补上 pyproject.yml 文件.
在大型的项目中, 一般都不追求花哨的代码, 而是追求稳定, 容易理解, 复杂度低的代码, 最完美的代码应该是入行的人一看就能理解, 又能完美的解决需求。但是人无完人, 很多时候在写代码可能会出现一些小问题, 而这些小问题靠人来检查是费时费力的, 同时又很难排查出来,这时就需要代码检查工具了。一般代码检查工具分为三类, 一类是检查代码风格, 并把不标准的代码风格格式化为标准的代码风格;另一类则是代码逻辑检查,他会检查代码逻辑, 代码复杂度, 引用的包是否有问题等等, 最后一类是代码安全检查, 比如是否在代码中引入密钥, 或者像在 Python 代码中写 eval 函数等.
Flake8 是由Python官方发布的一款辅助检测Python代码是否规范的工具,相对于目前热度比较高的 Pylint 来说, Flake8 检查规则灵活,支持集成额外插件,扩展性强。 Flake8 是对下面三个工具的封装:
1.PyFlakes:静态检查Python代码逻辑错误的工具.
2.Pep8:静态检查PEP8编码风格的工具.
3.NedBatchelder’s McCabe :静态分析Python代码复杂度的工具.
Flake8 除了支持上面3种功能外, 还支持通过插件的方式引入其他功能, 比如使用 flake8-docstrings 强制要求编写函数 docstring 等.
在项目中可以通过 poetry add flake8 --dev 引入flake8到dev依赖, 然后通过在根目录增加 .flake8 文件:
指定 Flke8 该如何执行, 最后调用命令 poetry run flake8. 即可.
毫无疑问, Python的语法让人能简洁的写出代码, 但是他的动态语言特性会使大型项目变得不牢固, 而 mypy 的出现恰好能解决这一问题。 mypy 是一个静态类型检查工具,它可以帮助我们像静态语言一样在运行代码之前就捕获到某些错误, 但是我们在写Python代码时, 要像静态语言一样, 会参数写上他的类型, 这就是Type Hints, 通过 mypy 和 Type Hints 的结合, 虽然会增加我们的代码量, 但它可以引入如下好处:
IDE
通过类型推断提供更好的代码补全和提示功能, 方便项目重构以及提前检查出错误。 2.强制你去思考动态语言程序的类型可能会帮助你构建更清晰的代码架构.
比如有如下一个函数:
一般来说无法知道这个函数要传什么类型的参数进去, 也许一开始是传 int 变量, 后面变为 str 变量, 而通过 Type Hints 则可以指定这个变量的类型是什么, 以及返回的类型是什么, 经过改造后将会变为:
这个函数的a, b参数以及返回的值类型都被标注为 int 类型, 这时候假如在程序内有两个调用:
他们虽然都能运行, 但是可以通过 mypy 检查出第二种调用方式是错误的。虽然这种示例简简单单, 看不出什么痛点, 但是在复杂的逻辑中, 他的优势就非常明显了.
在项目中可以通过 poetry add mypy --dev 安装依赖包, 然后通过在根目录增加 mypy.ini 文件:
指定 mypy 该如何执行, 最后调用 poetry run mypy . 即可 。
Python是一个动态语言, 而且不会对代码风格做强要求, 这就会导致一千个人一千种Python代码风格, 这同样在大型项目中非常糟糕的...好在Python生态中有很多自动格式化的工具, 但这里并不会详细对比他们的差异, 只是简要介绍下我在试用了多种后保留了以下3个工具(适不适合自己团队, 还是得自己试试才知道):
--in-place
: 直接对文件进行更改, 而不是把差异打印出来(用它就要相信他) --exclude
: 排除哪些文件/文件夹不进行格式化 --recursive
: 递归的遍历文件 --remove-all-unused-imports
: 删除所有未导入的依赖包 --ignore-init-module-imports
: 删除所有未导入的包时排除 __init__.py
文件 --remove-unused-variables
:删除未使用的变量 poetry add isort --dev
进行安装, isort支持 pyproject.toml
文件配置, 以下是我的一个常用配置: poetry add black --dev
进行安装, mypy同样支持 pyprojrct.toml
文件配置, 以下是我的一个常用配置(black的配置项不多): 自动格式化的工具引入到项目没多久后就会开始寻求自动化了, 因为每次提交之前都要手动跑一些自动格式化的脚本, 实在是太麻烦了, 好在有 pre-commit 这个专门为 git hooks 而生的工具.
pre-commit 是一个用于管理和维护多种语言的 git pre-commit hooks 框架,就像Python的包管理器 pip 一样,可以通过 pre-commit 将他人创建并分享的 pre-commit hooks 安装到自己的项目仓库中。 pre-commit 的出现大大减少了我们使用 git hooks 的难度,只需要在配置文件中指定想要的 hooks ,它会替你安装任意语言编写的 hooks 并解决环境依赖问题,然后在每次提交前执行 hooks .
一般来说, 通过 pip install pre-commit 就可以安装了, 但是为了环境隔离, 需要使用 poetry add pre-commit --dev 安装, 安装完后就可以在项目根目录创建文件 .pre-commit-config.yaml , 以下是我的配置, 除了上面提到的几个工具外, 还有一些其他脚本的校验工具
文件中的内容很简单, 它指明使用了哪些工具, 工具是哪个版本, 以及使用哪些 hook (一个仓库可能有多个hook), 每个参数的解释如下:
repo: 仓库url, pre-commit通过git来安装存在于github的工具 。
rev: 每个工具的版本, 这里是利用到git的tag属性 。
hooks/id: 每个仓库会有很多个hook, 通过hooks-id来选择要使用的hooks 。
hook/id/args: 每个hook都支持一些参数, args就是配置hook的参数 。
这些工具都会读取根目录的配置文件, 而 autoflake 我找不到他的 pyproject.toml 配置说明, 所以直接通过的 args 参数配置参数。之后就可以直接调用 hook 脚本, 如果是第一次引入已有项目则应该先手动调用 poetry run pre-commit run --all-files , 他会调用所有 hook 对项目进行检查, 然后再根据检查结果对代码和配置进行调整。调整完毕之后可以调用 poetry run pre-commit install 把 hook 脚本进行安装,它会自动安装在 .git/hooks/pre-commit 。安装后, 每执行次 git commit 时, 都会通过 git hooks 机制自动执行脚本, 自动对代码进行检查和格式化.
上面的配置文件是我的常用配置, pre-commit 的hook有很多, 不止这些, 如有兴趣可以到pre-commit hook合集(https://pre-commit.com/hooks.html)查阅所有hook 。
本地的hook只针对本地提交者, 而在团队协作中, 其他人员可以暂时屏蔽或者删除hook文件, 导致本地hook没办法达到强制的作用, 所以团队一般会在Github&Gitlab中的 pre-recevice 阶段配置一个自己的脚本, 用来跑上面的代码检测工具, 虽然两种的做法有点不同, 但核心步骤都是一样:
1.先拉取最新的代码到容器里 。
Redis
容器等等 3.代码检查, 这时候会运行代码质量检测工具, 如果有一个检测错误, 那么就拒绝提交, 并显示哪里错误了, 如果没有问题就走下一步.
4.测试阶段, 该阶段会运行测试用例,检测测试代码覆盖率是否合格, 同样的, 如果检测不合格就会拒绝提交, 成功就进入下一步.
isort
, black
等, 把项目的代码进行格式化。 一般每个公司都有自己的一套标准 CI/CD , 而他们的使用方法可能都会有些差别, 但核心原理也差不多, 以下会以开源项目为例介绍如何使用Github的action(这个功能是免费的!!!). 。
Gitlab的CI/CD相关文章比较多, 可以查阅网络或查阅书籍《持续交付》(https://book.douban.com/subject/6862062/), 也可以查看文章:https://www.mindtheproduct.com/what-the-hell-are-ci-cd-and-devops-a-cheatsheet-for-the-rest-of-us/, 如果对Gitlab hook有兴趣可以查阅Gitlab pre-receive webook 的添加与使用(treesir.pub/post/gitlab-pre-receive-webhook) 。
该例子来自于我的项目rap。首先在项目目录创建 script 目录, 这里面的目录可以被本地调用, 但主要还是用于 Github action , 首先创建一个install的脚本, 这个脚本用于安装依赖包:
注意这里是以 venv 为虚拟环境依赖的, 而不是我上面提到的 poetry . 使用 venv 的原因是线上一般是一个机器跑一个项目, 同时生产的机器都追求稳定, 这时候venv简单而稳定的好处就体现出来了, 所以比较推荐在线上使用 venv 。上面这个脚本就是创建一个虚拟环境, 然后根据 requirements-dev.txt 安装测试环境依赖.
依赖部分搞定了, 接下来就是告诉 Github action 该如何进行代码质量检查了, 于是编写一个check的脚本:
这个脚本就是简单的调用各个命令, 命令的顺序就如同上面一样, 先进行代码检查, 再跑测试用例, 最后进行代码格式化。这里的命令没有写各个的配置, 因为他们都会自动读取项目下的配置文件, 与我们的本地hook保持一致.
给Github action调用的脚本创建好后, 就开始创建真正的Github action文件了。首先在项目创建 .github/workflows 目录, 并在 .github/workflows 目录创建 test-suite.yml 文件(文件的更多说明见官方文档(https://docs.github.com/cn/actions/learn-github-actions/introduction-to-github-actions)):
文件编写完毕后就可以推送代码到远程了, 然后就可以到Github对应的项目地址查看action执行情况, 一般成功结果如下(这里只测一个Python3.7, 如果失败了, 你还会收到邮件提醒):
也可以点开查看某个步骤的详情, 比如检查代码的详情
这些工具都是我慢慢实践和整合后找到最符合自己的构建 Python 项目质量的工具集了, 但是这些工具只能检查表面情况, 而其他情况如代码逻辑是否有问题, 则需要编写测试用例后再运行才能知道.
而有些团队甚至会采用压力测试, 线上仿真测试等等, 这些工具/系统的引入和使用初期会带来很大的学习和时间成本, 但它们却能让项目一直保持茁壮成长, 减少线上项目Bug出现的次数(当然这些工具还有测试用例等等也要一起跟着维护).
原文链接:https://mp.weixin.qq.com/s/qOCMBqrmpdrLgTJPdlTjjA?utm_source=tuicool&utm_medium=referral 。
最后此篇关于使用哪些工具,可以提升 Python 项目质量的文章就讲到这里了,如果你想了解更多关于使用哪些工具,可以提升 Python 项目质量的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。
我正在处理一组标记为 160 个组的 173k 点。我想通过合并最接近的(到 9 或 10 个组)来减少组/集群的数量。我搜索过 sklearn 或类似的库,但没有成功。 我猜它只是通过 knn 聚类
我有一个扁平数字列表,这些数字逻辑上以 3 为一组,其中每个三元组是 (number, __ignored, flag[0 or 1]),例如: [7,56,1, 8,0,0, 2,0,0, 6,1,
我正在使用 pipenv 来管理我的包。我想编写一个 python 脚本来调用另一个使用不同虚拟环境(VE)的 python 脚本。 如何运行使用 VE1 的 python 脚本 1 并调用另一个 p
假设我有一个文件 script.py 位于 path = "foo/bar/script.py"。我正在寻找一种在 Python 中通过函数 execute_script() 从我的主要 Python
这听起来像是谜语或笑话,但实际上我还没有找到这个问题的答案。 问题到底是什么? 我想运行 2 个脚本。在第一个脚本中,我调用另一个脚本,但我希望它们继续并行,而不是在两个单独的线程中。主要是我不希望第
我有一个带有 python 2.5.5 的软件。我想发送一个命令,该命令将在 python 2.7.5 中启动一个脚本,然后继续执行该脚本。 我试过用 #!python2.7.5 和http://re
我在 python 命令行(使用 python 2.7)中,并尝试运行 Python 脚本。我的操作系统是 Windows 7。我已将我的目录设置为包含我所有脚本的文件夹,使用: os.chdir("
剧透:部分解决(见最后)。 以下是使用 Python 嵌入的代码示例: #include int main(int argc, char** argv) { Py_SetPythonHome
假设我有以下列表,对应于及时的股票价格: prices = [1, 3, 7, 10, 9, 8, 5, 3, 6, 8, 12, 9, 6, 10, 13, 8, 4, 11] 我想确定以下总体上最
所以我试图在选择某个单选按钮时更改此框架的背景。 我的框架位于一个类中,并且单选按钮的功能位于该类之外。 (这样我就可以在所有其他框架上调用它们。) 问题是每当我选择单选按钮时都会出现以下错误: co
我正在尝试将字符串与 python 中的正则表达式进行比较,如下所示, #!/usr/bin/env python3 import re str1 = "Expecting property name
考虑以下原型(prototype) Boost.Python 模块,该模块从单独的 C++ 头文件中引入类“D”。 /* file: a/b.cpp */ BOOST_PYTHON_MODULE(c)
如何编写一个程序来“识别函数调用的行号?” python 检查模块提供了定位行号的选项,但是, def di(): return inspect.currentframe().f_back.f_l
我已经使用 macports 安装了 Python 2.7,并且由于我的 $PATH 变量,这就是我输入 $ python 时得到的变量。然而,virtualenv 默认使用 Python 2.6,除
我只想问如何加快 python 上的 re.search 速度。 我有一个很长的字符串行,长度为 176861(即带有一些符号的字母数字字符),我使用此函数测试了该行以进行研究: def getExe
list1= [u'%app%%General%%Council%', u'%people%', u'%people%%Regional%%Council%%Mandate%', u'%ppp%%Ge
这个问题在这里已经有了答案: Is it Pythonic to use list comprehensions for just side effects? (7 个答案) 关闭 4 个月前。 告
我想用 Python 将两个列表组合成一个列表,方法如下: a = [1,1,1,2,2,2,3,3,3,3] b= ["Sun", "is", "bright", "June","and" ,"Ju
我正在运行带有最新 Boost 发行版 (1.55.0) 的 Mac OS X 10.8.4 (Darwin 12.4.0)。我正在按照说明 here构建包含在我的发行版中的教程 Boost-Pyth
学习 Python,我正在尝试制作一个没有任何第 3 方库的网络抓取工具,这样过程对我来说并没有简化,而且我知道我在做什么。我浏览了一些在线资源,但所有这些都让我对某些事情感到困惑。 html 看起来
我是一名优秀的程序员,十分优秀!