Pythonのコード改善のためのツール5つを試してみた


このエントリーをはてなブックマークに追加

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

  • 用途:スタイルチェック
    • PEP 8で規定されているPython公式のスタイルガイドに違反する箇所を見つけてくれる。
  • 詳細

出力は以下のとおりです。空白行やスペースの不足が指摘されています。

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に関するエラーのみが指摘されています。

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の和になっていることがわかります。

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

型ヒントのためのツールです。自分はまだ理解できていません。

  • 用途: Optional Static Typing for Python
    • Python 3.6に導入された型ヒントを使っている人向けのツール。型の誤りを静的に解析する。

PyChecker

  • 用途:スタイルチェック + エラー解析
  • 詳細
    • Python 2.x系が対象。開発が止まっているようなので今から使う理由はないでしょう。

個人的な結論

  • まずはflake8をデフォルトで使う
  • flake8で足りないところがあれば、Pylintを併用するか、flake8の適当なプラグインを見つけて導入する

参考