Pylint 利用ノート

本稿では Pylint の利用について記す。

Pylint は Python で書かれたコードを解析して、構文エラーの有無、コーディング規約違反(特に PEP8 に対する)の有無、設計のまずそうなところを発見するためのコマンドラインツールである。

同種のパッケージは他にも有名なものがあるが、Pylint は出力のうるささに定評があるようなので、当サイトはこれを採用している。

Note

  • OS
    • Windows 7 Home Premium x64 SP1
    • Windows 10 Home x64
  • 本稿において、利用した各パッケージのバージョンは次のとおり。

関連リンク

Pylint
公式サイト。インストール方法から基本的な利用方法、応用等が文書化されている。

インストール

一般のサードパーティー製 Python パッケージのインストール手順 を参照してインストールする。

$PYTHONDIR/Scripts フォルダーに、ファイル名が pylint で拡張子が異なるものが 3 つあるのが確認できる。内容は次のようなものだ:

  • pylint: Python スクリプト。単に pylint.run_pylint() を実行するだけ。
  • pylint.bat: Windows のバッチスクリプト。 Python に上記スクリプトをコマンドライン引数として渡して実行するだけ。
  • pylint.exe: Windows の実行ファイル。

私は Python を利用する際には原則的に Cygwin のコマンドライン (Bash) から呼び出すことにしている。環境変数 $PATH には既に $PYTHONDIR/Scripts を含ませてあるゆえ、私が Pylint をコマンドラインから呼び出すときの記法は次のようになる。

$ pylint.bat args
# or
$ pylint.exe args

.pylintrc を作成する

Pylint の設定ファイルについて記す。デフォルトでは Pylint はファイル $HOME/.pylintrc の内容を設定として取り扱う(実際は他にも候補がある)。このファイルが存在しない場合、Pylint は出力の最初に警告

No config file found, using default configuration.

を発する。設定ファイルの有無は Pylint の機能に支障はないが、この警告文が毎度目につくと煩わしいので、まずはダミーの設定ファイルを作成しておく。

$ pylint --generate-rcfile > ~/.pylintrc

次にこの設定ファイルのスケルトンに対して構文チェックをしておこう。単に pylint --version をすることで、 .pylintrc のチェックをさせることにもなる。

$ pylint --version
Warning: option ignore-iface-methods is obsolete and it is slated for removal in Pylint 1.6.
Warning: option zope is obsolete and it is slated for removal in Pylint 1.6.
pylint-script.py 1.5.4,
astroid 1.4.4
Python 3.5.2 |Continuum Analytics, Inc.| (default, Jul  5 2016, 11:41:13) [MSC v.1900 64 bit (AMD64)]

上記のような Warning が出力されていれば、 .pylintrc をエディターで開いて、対応する項目を削除しておくとよい。

Pylint の設定ファイルはプロジェクトごとにコーディングルールに沿って微調整したものを用意するのが普通だろう。自動テストの一環としてコード解析を行う工程が想像できる。しかし、本稿は私個人の用途を想定しているので、その点については深入りしない。深入りしないが、Pylint が設定ファイルを指定する機能があることは承知している。

実践例

ここでは私が実際に行っている Pylint の利用例を示していく。とは言え、利用目的が冒頭で述べたように単純であるがゆえに、利用例の幅はかなり狭い。

よく使うコマンドラインパターン

私が実際の作業で使う Pylint のコマンドラインを紹介する。サンプルでは Python のコードファイル名をすべて mymodule.py として記すが、モジュールでなくスクリプトでも同じである。

スクリプト単体の構文チェック

Pylint はオプションなしで実行すると、どんなに品の良いコードを与えたとしても、たいへんな量のテキストを出力することで知られている。特に出力後半の統計部分が個人的には用がないので常に -rn, (or --reports=n) を指示する習慣を身につけた。興味があるのは、コードのどの行がどのような「まずさ」を有するかということだけなのだ。

# Suppress statistics, i.e. display only
# R: refactor, C: convention, W: warning, and E: error.
$ pylint -rn mymodule.py

# Display only errors (E).
$ pylint -E mymodule.py

Pylint の出力はコード解析結果と統計結果のふたつの部分からなる。前述のとおり後者はカットする。解析結果は与えたモジュール名に対して、問題のタイプ、行番号、メッセージのリストという構成だ。一回見ればだいたい理解できるはずなので、ここに出力例を掲載することは差し控える。

パッケージ単位での構文チェック

コマンドラインでの呼び出し方法に変わりはない。モジュールを示すファイル名の代わりにパッケージ名を与えればよい。公式ドキュメントによると、開発版の(=確かめたい)パッケージと、環境変数 $PYTHONPATH にあるそれとを Pylint に混同させないように注意する必要があるそうだ。

# Specify the package name.
$ pylint -rn mypackage

Python コード修正

Pylint のコード解析結果(私は RCWE リストと呼んでいる)にらめっこしながら、対応しよう。修正のやり方には二通りあり、ひとつは忠告に従って素直にコードを修正することで、もう一つのやり方は、Pylint に勘弁してもらうというものだ。ここではこれらを順に説明していく。

地道にコードのほうを修正する

例えば C:155, 0: Line too long (81/80) (line-too-long) というコード解析結果が出たとしよう。このときコードを修正するのであれば、テキストエディターで対象のモジュールファイルを開いて、

  1. 155 行目にジャンプする。
  2. 適宜テキストを編集し、行の長さを 81 文字から 80 字以下に切り詰める。おそらく、行の途中で(Python の構文として違法にならぬように)改行することになる。

という手順を踏むのがひとつの解法だ。テキスト編集で解決できるならば、それが単純でよさそうだ。

Pylint を黙らせる

Pylint の忠告に従いたいが、難しい場合もある。あるいは、Pylint が勘違いして不当なエラーを報告する場合もある。このような場合は、対応するコードの近所に「抑止命令」コメントを追加することでしのぐ。

例を説明する。次のような E が出てしまった:

E:242,34: Class 'AbstractMapper' has no '__subclasses__' member (no-member)

状況はこうだ。私は自作のモジュールで AbstractMapper という抽象クラスを定義した。冒頭だけ引用すると次のような構成になっている。 ABCMeta 等については Python のマニュアルを参照して欲しいが、こうすることで私のクラスには __subclasses__ というメンバーが確かに存在する。

from abc import ABCMeta
from abc import abstractmethod

class AbstractMapper(metaclass=ABCMeta):
    """The abstract class that represents the SNES ROM layout."""
    ...

しかたがないので、このクラスの宣言の直前に次のコメントを追加しておく。

# pylint: disable=no-member
class AbstractMapper(metaclass=ABCMeta):
    ...

こうすることで、次からの Pylint のメッセージは次のように変わり、やや安心できる。

I: 242, 0: Locally disabling no-member (E1101) (locally-disabled)

なお、出力抑止をしたいエラー項目はエラー名だけでなく、エラー番号でも指定できる。カンマ区切りで複数のエラー項目を指示することもできるし、抑止コメントを抑止する項目数だけ書いてもよい。