Pythonのコードを改善するためのツールについて一通り試してみました。各ツールのインストール方法や使い方については Pythonのスタイルガイドとそれを守るための各種Lint・解析ツール5種まとめ! - Sider Blog に詳細にまとまっているのでおすすめです。
サンプルコード
以下のサンプルコードを対象に、各ツールの出力を確かめてみます。
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)
このスクリプトをsample.py
という名前で保存したのち、以下のスクリプトで実験をしました。各ツールはすべてデフォルトです。
for name in pycodestyle \ pydocstyle \ pyflakes \ flake8 \ pylint do echo "=================" echo ${name} echo "=================" echo "version:" $(${name} --version) ${name} sample.py echo "" done
各ツールの紹介
pycodestyle
- 用途:スタイルチェック
- 詳細
- 以前までは "pep8" というツール名だったが、pycodestyleに改名された (参考:pep8 が pycodestyle に変わった話)
出力は以下のとおりです。空白行やスペースの不足が指摘されています。
version: 2.0.0 sample.py:5:1: E302 expected 2 blank lines, found 1 sample.py:5:15: E231 missing whitespace after ','
pydocstyle
- 用途:docstring専用のスタイルチェック
- PEP 257で規定されているdocstring (moduleや関数の最初に記される、
"""
と"""
で囲まれたコメントのこと)の書き方に違反する箇所を見つけてくれる。
- PEP 257で規定されているdocstring (moduleや関数の最初に記される、
- 詳細
- 以前までは "pep257" というツール名だったが、pydocstyleに改名された (参考:Python: pep8 は pycodestyle になったし pep257 は pydocstyle になった - CUBE SUGAR CONTAINER)
出力は以下のとおりです。docstringに関するエラーのみが指摘されています。
version: 2.1.1 sample.py:1 at module level: D100: Missing docstring in public module sample.py:5 in public function `func1`: D300: Use """triple double quotes""" (found '''-quotes) sample.py:5 in public function `func1`: D400: First line should end with a period (not 'b') sample.py:5 in public function `func1`: D403: First word of the first line should be properly capitalized ('Return', not 'return')
pyflakes
- 用途:エラー解析
- 詳細
- ソースファイルを解析して、importしたけど使っていないモジュールや、未使用の変数などを報告。
- pycodestyleとは違い、コードのスタイルについては分析しない。
- 高速さに重点を置く。Pylintよりも高速。
- 正しいコードを過ってエラーと報告しないように細心の注意が払われている。
- 解析はファイル単位で行われるので、importで読み込むファイルにまたいだ解析はできない。
- もっと詳しい分析が必要な場合は、Flake8を使う。
出力は以下のとおりです。未使用のimport文、未使用の変数が報告されています。
version: 1.2.3 sample.py:1: 'time' imported but unused sample.py:7: local variable 'varC' is assigned to but never used
Flake8
- 用途:スタイルチェック + エラー解析 + 複雑度チェック
- 詳細
- pycodestyle + pyflakes + mccabe(複雑度チェッカー)
- オプションやプラグインが豊富でカスタマイズの幅が広い。
- 自分が調べた限りでは一番人気がある。
出力は以下のとおりです。ちょうど出力がpycodestyleとpyflakesの和になっていることがわかります。
version: 2.6.2 (pycodestyle: 2.0.0, mccabe: 0.5.3, pyflakes: 1.2.3) CPython 3.6.4 on Windows 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
Pylint
- 用途:スタイルチェック + エラー解析
- 詳細
- 老舗のツール。effective pythonで推されていた。
- Plugin機能がある。
出力は以下のとおりです。flake8では報告されなかった、変数名の規則違反(varA
など)や、意味のない文('3 + 5')が報告されています。
最終行にこのコードの得点が表示されるのが面白いです。この場合10点満点中0点という意味です。さらには負の点数になることもあります。
No config file found, using default configuration Python 3.6.4 |Anaconda custom (64-bit)| (default, Jan 16 2018, 10:22:32) [MSC v.1900 64 bit (AMD64)] No config file found, using default configuration ************* Module sample C: 5, 0: Exactly one space required after comma def func1(varA,varB): ^ (bad-whitespace) C: 8, 0: Unnecessary parens after 'return' keyword (superfluous-parens) C: 1, 0: Missing module docstring (missing-docstring) C: 5, 0: Argument name "varA" doesn't conform to snake_case naming style (invalid-name) C: 5, 0: Argument name "varB" doesn't conform to snake_case naming style (invalid-name) C: 7, 4: Variable name "varC" doesn't conform to snake_case naming style (invalid-name) W: 7, 4: Unused variable 'varC' (unused-variable) W: 12, 0: Statement seems to have no effect (pointless-statement) W: 1, 0: Unused import time (unused-import) ------------------------------------------------------------------ Your code has been rated at 0.00/10 (previous run: 0.00/10, +0.00)
flake8のプラグイン
flake8のプラグインを別途インストールすることで、flake8にルールを追加することが可能です。pip search flake8-
するとわかるのですが、大量のプラグインが存在しています。ここでは2つだけ紹介します。
hacking
- 用途:Flake8にOpenstack社のルールを追加するプラグイン
- 詳細
pip install hacking
したあとにflake8を呼び出すと、flake8に、Openstack社が独自に追加したルールが追加される
出力は以下のとおりです。H
で始まる行が、flake8に追加された検出された項目になります。この例だとimport文の順番がアルファベット順になっていなかったことで怒られています。
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) CPython 3.6.4 on Windows sample.py:1:1: F401 'time' imported but unused sample.py:2:1: H306 imports not in alphabetical order (time, sys) sample.py:3:1: H306 imports not in alphabetical order (sys, fractions) 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
flake8-docstrings
- 用途:Flake8に
pydocstyle
のルールを追加するプラグイン - 詳細
pip install pydocstyle
したあとにflake8を呼び出すと、flake8に、pydocstyle
のルールが追加される
出力は以下のとおりです。D
で始まる行がdocstringに関する報告です。
version: 2.6.2 (pycodestyle: 2.0.0, mccabe: 0.5.3, pyflakes: 1.2.3, flake8-docstrings: 1.3.0, pydocstyle: 2.1.1) CPython 3.6.4 on Windows sample.py:1:1: D100 Missing docstring in public module sample.py:1:1: F401 'time' imported but unused sample.py:5:1: D300 Use """triple double quotes""" sample.py:5:1: D400 First line should end with a period sample.py:5:1: D403 First word of the first line should be properly capitalized 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
サンプルコードの修正例
すべてのエラーや警告が消えるまで修正したのが以下のコードです。良いコードになったでしょうか?
"""Sample for hatena diary.""" import fractions import sys def func1(var_a, var_b): """Return sum of a and b.""" return var_a + var_b print(func1(fractions.Fraction(1, 2), fractions.Fraction(1, 3))) sys.exit(0)
その他のツール
mypy
型ヒントのためのツールです。自分はまだ理解できていません。
PyChecker
- 用途:スタイルチェック + エラー解析
- 詳細
- Python 2.x系が対象。開発が止まっているようなので今から使う理由はないでしょう。
個人的な結論
- まずはflake8をデフォルトで使う
- flake8で足りないところがあれば、Pylintを併用するか、flake8の適当なプラグインを見つけて導入する
flake8についてはこちらの記事により詳しい使い方をまとめました。
参考
- Pythonのスタイルガイドとそれを守るための各種Lint・解析ツール5種まとめ! - Sider Blog
- pep8(現pycodestyle), pyflakes, flake8, hacking, pylintの使い方について詳細に記述されています。
- About style guide of python and linter tool. pep8, pyflakes, flake8, haking, Pylint.
- 上の英語版。著者はともにSider株式会社。
- Python の Lint (文法チェッカ) まとめ - flake8 + hacking を使う -
- さらに多くのツール群の紹介。
- 4 Best open source Python static analysis tools as of 2018 - Slant
- Pylint, flake8, mypy, pyflakesに対する人気投票
- 5 Best Python code linters as of 2018 - Slant
- 上と類似
- Any advantages of Flake8 over PyLint? : Python
- Code Style — The Hitchhiker's Guide to Python
- pylint や pyflakes がパースできないような変なコードはそもそも避けるべきという話題
- Flake8 のプラグイン機構についてのお話 - SideCI TechBlog
- flake8のプラグインの作り方