Pythonのコード改善のためのツール5つを試してみた - minus9d's diary の中で個人的にもっともよさそうだと感じたflake8について、使い方を詳しく調べました。
インストール
$ pip install flake8
$ flake8 --version
すると、flake8のバージョンと、インストール済のflake8のプラグインの一覧が出てきます。以下に例を示します。
$ flake8 --version
2.6.2 (pycodestyle: 2.0.0, mccabe: 0.5.3, pyflakes: 1.2.3) CPython 3.6.4 on Windows
これはflake8のプラグインを何も入れていない状態での表示例です。ここで表示されるpycodestyle
, mccabe
, pyflakes
が、flake8が初めから備える基本の3点セットです。pycodestype
は「PEP8のスタイル」を、mccabe
は「複雑度」を、pyflakes
は「エラー解析」をチェックしてくれるものです。
もしあなたが過去にflake8のプラグインをインストールしているとすると表示量が増えます。例えば以前にflake8のプラグインhacking
, flake8-import-order
, flake8-docstring
を以下のコマンド
$ pip install hacking
$ pip install flake8-import-order
$ pip install flake8-docstrings
でインストールしていたとすると、--version
で表示されるのは以下のようになります。
$ flake8 --version
2.6.2 (pycodestyle: 2.0.0, mccabe: 0.5.3, ProxyChecker: 0.0.1, hacking.core: 0.0.1, pyflakes: 1.2.3, import-order: 0.18, flake8-docstrings: 1.3.0, pydocstyle: 2.1.1) CPython 3.6.4 on Windows
以下ではプラグインは何も入れていないものとして話を進めます。
コードの解析方法は2つあります。1つ目は、以下のように特定のファイルを指定する方法。
$ flake8 sample.py
2つ目は、ディレクトリを指定する方法。
$ flake8 /path/to/dir
コードの解析例
以下のPython 3コードをsample.py
という名前で保存して
import time
import sys
import fractions
def func1(varA,varB):
'''return sum of a and b'''
varC = 42
return (varA + varB)
print(func1(fractions.Fraction(1, 2), fractions.Fraction(1, 3)))
3 + 5
sys.exit(0)
$ flake8 sample.py
でコード解析した結果は以下になります。
sample.py:1:1: F401 'time' imported but unused
sample.py:5:1: E302 expected 2 blank lines, found 1
sample.py:5:15: E231 missing whitespace after ','
sample.py:7:5: F841 local variable 'varC' is assigned to but never used
読み方は、"ファイルパス":行番号":"列番号":"コード":エラー内容 です。
コードの詳細は Warning / Error codes — flake8 2.6.0 documentation を参照してください。
表示の詳細化
--show-source
オプションを付けると、ソースコードの該当部分もあわせて表示してくれます。
$ flake8 --show-source sample.py
sample.py:1:1: F401 'time' imported but unused
import time
^
sample.py:5:1: E302 expected 2 blank lines, found 1
def func1(varA,varB):
^
sample.py:5:15: E231 missing whitespace after ','
def func1(varA,varB):
^
sample.py:7:5: F841 local variable 'varC' is assigned to but never used
varC = 42
^
さらに--show-pep8
オプションを付けると、PEP8のルールを表示してくれます。いちいちメッセージの意味を調べる必要がなくて便利です。
$ flake8 --show-source --show-pep8 sample.py
sample.py:1:1: F401 'time' imported but unused
import time
^
sample.py:5:1: E302 expected 2 blank lines, found 1
def func1(varA,varB):
^
Separate top-level function and class definitions with two blank lines.
Method definitions inside a class are separated by a single blank line.
Extra blank lines may be used (sparingly) to separate groups of related
functions. Blank lines may be omitted between a bunch of related
one-liners (e.g. a set of dummy implementations).
Use blank lines in functions, sparingly, to indicate logical sections.
Okay: def a():\n pass\n\n\ndef b():\n pass
Okay: def a():\n pass\n\n\nasync def b():\n pass
Okay: def a():\n pass\n\n\n# Foo\n# Bar\n\ndef b():\n pass
Okay: default = 1\nfoo = 1
Okay: classify = 1\nfoo = 1
E301: class Foo:\n b = 0\n def bar():\n pass
E302: def a():\n pass\n\ndef b(n):\n pass
E302: def a():\n pass\n\nasync def b(n):\n pass
E303: def a():\n pass\n\n\n\ndef b(n):\n pass
E303: def a():\n\n\n\n pass
E304: @decorator\n\ndef a():\n pass
E305: def a():\n pass\na()
E306: def a():\n def b():\n pass\n def c():\n pass
sample.py:5:15: E231 missing whitespace after ','
def func1(varA,varB):
^
Each comma, semicolon or colon should be followed by whitespace.
Okay: [a, b]
Okay: (3,)
Okay: a[1:4]
Okay: a[:4]
Okay: a[1:]
Okay: a[1:4:2]
E231: ['a','b']
E231: foo(bar,baz)
E231: [{'a':'b'}]
sample.py:7:5: F841 local variable 'varC' is assigned to but never used
varC = 42
^
Indicates that a variable has been explicitly assigned to but not actually
used.
79文字制限の緩和
PEP8で決められている1行79文字制限が厳しすぎると感じる場合は--max-line-length
オプションで制限を緩和できます。
$ flake8 --max-line-length=100 sample.py
自分が修正したコードだけをチェック
既存コードを修正してコミットするとき、既存部分のスタイル違反はいったん見て見ぬふりをして、自分が修正した部分だけにflake8でチェックをかけたいことがあります。そのときに使えるのが--diff
オプションです。git diff
の結果を以下のようにパイプで受けます。
$ git diff sample.py | flake8 --diff
複雑度のチェック
--max-complexity N
(Nは整数)をつけると、コードの複雑度(具体的にはサイクロマチック数)が閾値Nを超えている場合に、警告を出せるようになります。使い方の例は以下です。
$ flake8 --max-complexity 12 sample.py
解析除外
flake8による解析を行いたくないファイルには、
という行を追加します。
flake8による解析を行いたくない行には、行末に# noqa
を付けます。noqa
とはno quality assurance
の略だそうです。
noqa
を無視して解析をかけるには--disable-noqa
オプションを使います。
ルールのカスタマイズ
特定のルールを無視したいときは--ignore
を使います。例えば以下のようにするとE1, E23, or W503で始まるルールを無視できます。
$ flake8 --ignore=E1,E23,W503 sample.py
逆に、特定のルールだけを有効にしたいときは--select
を使います。例えば以下のようにするとEで始まるルールだけが有効になります。
$ flake8 --select=E sample.py
自動修正は不可能
指摘点を自動修正する機能はflake8にはないようです。autopep8, black, yapfなどのツールを使ってください。(参考:formatting - How do I autoformat some Python code to be correctly formatted? - Stack Overflow)
参考URL