Python由语法简介和自由而著名,如果你不想库里的代码乱七八糟,统一编码规范尤其重要。
比起人来做大量的代码审查,使用软件进行代码检查和优化对于编码规范是一个更好的主意。
以下,主要探索了pylint、flake8、black、yapf、isort等软件的安装及使用。
编码检查
统一代码的第一步是统一编码,主要有两个方面需要注意,fileencoding和fileformat。
根据PEP8的规定,Python3使用UTF-8编码,Python2使用ASCII编码。fileformat根据所在系统确定。
另外,在Python标准库中,所有标识符、字符串文本、注释都必须使用ASCII。
列出所有文件的编码信息
如果没有子目录:
file *
如果有子目录:
find . -name '*' | xargs file | grep -v directory
如果有with CRLF line terminators
,说明是文件类型是dos
。
列出所有dos
编码文件:
find . -name '*' | xargs file | grep CRLF
批量转码
将所有GBK(ISO-8859)
转为UTF-8
:
依赖:enca
find . -name '*' | xargs file | grep ISO-8859 | xargs -d: -n1 | grep .py | xargs enca -L zh_CN -x utf-8
将所有dos
转为unix
:
依赖:dos2unix
find . -name '*' | xargs file | grep CRLF | xargs -d: -n1 | grep .py | xargs dos2unix
Pylint
简介
Pylint是一个Python代码检查工具,它使用编码标准来检查代码问题,并提出重构建议。
在最后Pylint会输出代码全局评分分数,这可以用来测试修改代码后的效果。
安装
1 | sudo pip install pylint |
pylint3 --version
1 | pylint3 2.2.2 |
使用
1 | pylint [options] <modules_or_packages> |
flake8
简介
Flake8 是由Python官方发布的一款辅助检测Python代码是否规范的工具,相对于目前热度比较高的Pylint来说,Flake8检查规则灵活,支持集成额外插件,扩展性强。
Flake8是对下面三个工具的封装:
1)PyFlakes:静态检查Python代码逻辑错误的工具。
2)pycodestyle: 静态检查PEP8编码风格的工具。
3)NedBatchelder’s McCabe script:静态分析Python代码复杂度的工具。
安装
1 | sudo python -m pip install flake8 |
Flake8最好安装在对应的Python版本。如果要想Flake8能够正确地解析 Python 3.5中的新语言特性(例如) ,那么需要将它安装在3.5上,以便Flake8能够理解这些特性。
使用
1 | flake8 <modules_or_packages> |
如果在多个Python版本上安装了Flake8,最好使用Python<version> -m Flake8
来运行Flake8。
如果只想看特定的警告或错误:
1 | flake8 --select E123,W503 <modules_or_packages> |
如果想忽略一个特定的警告或错误:
1 | flake8 --ignore E24,W504 <modules_or_packages> |
Black
简介
Black是不妥协的Python代码格式化程序。这代表着用户不能细化代码风格。
Black默认会直接重构文件。
安装
1 | sudo pip install black / pip install black |
当前版本:black, version 20.8b1
使用
1 | black [OPTIONS] {source_file_or_directory} / python -m black [OPTIONS] {source_file_or_directory} |
不加参数时,Black默认会直接用新文件覆盖旧文件。
Option | 参数 | 说明 |
---|---|---|
-c | TEXT | 格式化作为字符串传入的代码 |
-l | INTEGER | 每行允许多少字符 |
-t | [py27\py33\py34\py35\py36\py37\py38] | 输出支持的Python版本 |
—pyi | 格式化所有输入文件,而不考虑文件扩展名(在将源管道输送到标准输入时很有用) | |
-S | 跳过字符串规范化,不规范化字符串引号或前缀 | |
—check | 不要写回文件,只需返回状态。0表示不会返回任何代码。返回代码1表示某些文件将被重新格式化。返回代码123表示存在内部错误。 | |
—diff | 不要写回文件,只需在stdout上为每个文件输出一个diff | |
—color / —no-color | 当 —diff设置,此项决定是否着色diff输出 | |
—fast / —safe | 如果有 —fast,跳过临时的健全性检查 | |
—include | TEXT | 匹配递归搜索中应包含的文件和目录的正则表达式。空值表示包含所有文件,而不考虑其名称。对所有平台(Windows)上的目录使用正斜杠。先计算排除,再计算包含。 |
—exclude | TEXT | 匹配递归搜索时应排除的文件和目录的正则表达式。空值表示不排除任何路径。对所有平台(Windows)上的目录使用正斜杠。 |
—force-exclude | TEXT | 类似—exclude,但与此正则表达式匹配的文件和目录将被排除,即使它们作为参数显式传递。 |
-q | 不向stderr发出非错误消息。仍会发出错误;使用2>/dev/null使其静音 | |
-v | 还向stderr发送有关由于—exclude而未更改或被忽略的文件的消息 | |
—version | 输出版本信息 | |
—config | FILE | 从文件路径读取配置 |
-h | 输出帮助信息 |
用这个软件在我的某个pyhton文件试了一下,代码变得好看了不少:
1 | -class DBOperation(): |
yapf
简介
目前用于 Python 的大多数格式化程序——例如 autopep8和 pep8ify ——都是用来从代码中删除 lint 错误的。这有一些明显的局限性。例如,符合 PEP 8准则的代码可能不会被重新格式化。但这并不意味着代码看起来很好。
YAPF 采取了不同的方法。它是基于Clang格式 ,由丹尼尔贾斯珀开发。本质上,算法将代码重新格式化为符合样式指南的最佳格式,即使原始代码没有违反样式指南。
这个想法也类似于 Go 编程语言的“ gofmt”工具: 结束所有关于格式化的神圣战争——如果一个项目的整个代码库只是简单地通过 YAPF 管道进行修改,那么这种风格在整个项目中保持一致,并且在每次代码审查中争论风格也没有意义。
安装
YAPF 支持 Python 2.7 和 3.6.4+。YAPF 需要在程序代码对应的Python版本下运行。
1 | pip install yapf |
如果你使用的是Python2.7并且希望启动多进程:
1 | pip install futures |
使用
1 | usage: yapf [-h] [-v] [-d | -i] [-r | -l START-END] [-e PATTERN] |
YAPF默认是输出格式化之后的程序代码,加上-d之后输出的是更改的地方,加上-i之后是直接覆盖原代码。
isort
简介
isort是import sort的缩写,用于自动排序imports。
安装
1 | pip install isort |
使用
示例,优化之前:
1 | from my_lib import Object |
优化之后:
1 | from __future__ import absolute_import |
1 | usage: __main__.py [-h] [-a ADD_IMPORTS] [-ac] [-af] |
pre-commit
简介
Git hooks 可让您在想要提交或推送时运行检查脚本。这使我们能够在每次提交/推送时,对将要提交的代码进行检查、优化代码格式、或者对提交的图片进行压缩等等任务。
钩子都被存储在 Git 目录下的 hooks 子目录中。 也即绝大部分项目中的 .git/hooks 。 当你用 git init 初始化一个新版本库时,Git 默认会在这个目录中放置一些示例脚本。这些脚本除了本身可以被调用外,它们还透露了被触发时所传入的参数。 所有的示例都是 shell 脚本,其中一些还混杂了 Perl 代码,不过,任何正确命名的可执行脚本都可以正常使用 —— 你可以用 Ruby 或 Python,或其它语言编写它们。 这些示例的名字都是以.sample 结尾,如果你想启用它们,得先移除这个后缀。
把一个正确命名且可执行的文件放入 Git 目录下的 hooks 子目录中,即可激活该钩子脚本。 这样一来,它就能被 Git 调用。
pre-commit用于检查即将提交的快照。在git add
之后,在执行git commit
时执行脚本,如果脚本以0值退出就继续提交,非0就驳回提交的操作。可以用 git commit --no-verify
来绕过这个环节。