让你的包更规范

开发 Python 包

James Fulton

Climate informatics researcher

认识 flake8

  • 标准 Python 风格见 PEP8
  • 风格指南规定代码布局
  • 使用 pytest 查找错误
  • 使用 flake8 查找风格问题
开发 Python 包

运行 flake8

静态代码检查器——读取代码但不运行

flake8 features.py
features.py:2:1: F401 未使用的导入 'math'
..
<filename>:<line number>:<charcter number>:<error code> <desciption>
开发 Python 包

用输出改进代码质量

 1. import numpy as np
 2. import math
 3.
 4. def mean(x):
 5.    """Calculate the mean"""
 6.    return np.mean(x)
 7. def std(x):
 8.     """Calculate the standard deviation"""
 9.     mean_x = mean(x)
10.     std = mean((x-mean(x))**2)
11.     return std
12. 
flake8 features.py
2:1: F401 未使用的导入 'math'

4:1: E302 预期 2 个空行,实际为 1 个
7:1: E302 预期 2 个空行,实际为 0 个
5:4: E111 缩进不是 4 的倍数 6:4: E111 缩进不是 4 的倍数
9:5: F841 局部变量 'mean_x' 被赋值但未使用
开发 Python 包

用输出改进代码质量

 1. import numpy as np
 2.
 3.
 4. def mean(x):
 5.     """Calculate the mean"""
 6.     return np.mean(x)
 7. 
 8. 
 9. def std(x):
10.     """Calculate the standard deviation"""
11.     mean_x = mean(x)
12.     std = mean((x - mean_x)**2)
13.     return std
14. 
flake8 features.py


开发 Python 包

有意违反规则

quadratic.py

4. ...
5. quadratic_1 = 6 * x**2 + 2 * x + 4;
6. quadratic_2 = 12 * x**2 + 2 * x + 8
7. ...
开发 Python 包

有意违反规则

quadratic.py

4. ...
5. quadratic_1 =  6 * x**2 + 2 * x + 4;
6. quadratic_2 = 12 * x**2 + 2 * x + 8
7. ...
flake8 quadratic.py
quadratic.py:5:14: E222 运算符后有多个空格
quadratic.py:5:35: E703 语句以分号结束
开发 Python 包

有意违反规则

quadratic.py

4. ...
5. quadratic_1 =  6 * x**2 + 2 * x + 4; # noqa
6. quadratic_2 = 12 * x**2 + 2 * x + 8
7. ...
flake8 quadratic.py

开发 Python 包

有意违反规则

quadratic.py

4. ...
5. quadratic_1 =  6 * x**2 + 2 * x + 4; # noqa: E222
6. quadratic_2 = 12 * x**2 + 2 * x + 8
7. ...
flake8 quadratic.py
quadratic.py:5:35: E703 语句以分号结束
开发 Python 包

flake8 设置

不使用注释忽略风格违规

flake8 --ignore E222 quadratic.py
quadratic.py:5:35: E703 语句以分号结束
flake8 --select F401,F841 features.py
2:1: F401 未使用的导入 'math'
9:5: F841 局部变量 'mean_x' 被赋值但未使用
开发 Python 包

用 setup.cfg 配置包设置

创建 setup.cfg 保存设置

包文件结构

.
|-- example_package
|   |-- __init__.py
|   `-- example_package.py
|-- tests
|   |-- __init__.py
|   `-- test_example_package.py
|-- README.rst
|-- LICENSE
|-- MANIFEST.in
`-- setup.py
开发 Python 包

用 setup.cfg 配置包设置

创建 setup.cfg 保存设置

[flake8]


ignore = E302
exclude = setup.py
per-file-ignores = example_package/example_package.py: E222

包文件结构

.
|-- example_package
|   |-- __init__.py
|   `-- example_package.py
|-- tests
|   |-- __init__.py
|   `-- test_example_package.py
|-- README.rst
|-- LICENSE
|-- MANIFEST.in
|-- setup.py
`-- setup.cfg
开发 Python 包

整个包

$ flake8

包文件结构

.
|-- example_package
|   |-- __init__.py
|   `-- example_package.py
|-- tests
|   |-- __init__.py
|   `-- test_example_package.py
|-- README.rst
|-- LICENSE
|-- MANIFEST.in
|-- setup.py
`-- setup.cfg
开发 Python 包

尽量少用过滤

最少过滤

  1. # noqa : <code>
  2. # noqa
  3. setup.pyper-file-ignores
  4. setup.cfgexcludeignore

最多过滤

开发 Python 包

Passons à la pratique !

开发 Python 包

Preparing Video For Download...