先日の記事で Python 2.x/3.x の互換性に関するツールをいくつか紹介したけど、詳しい使い方までは書くことができなかった。 今回は、その中のひとつ pylint (の --py3k オプション) について紹介してみる。
pylint とは
pylint は Python で書かれたソースコードを静的に解析して、使われていない箇所 (デッドコード) や、あるいは不具合の元となるような危険な記述を見つけ出して教えてくれるサードパーティ製のツール。 Python を書くのであれば、エディタや CI サーバなどに組み込んで是非ともかけておきたいもののひとつ。
最近になって、この pylint に --py3k というオプションが追加された。 Python 2.x と 3.x では、使用できるシンタックスが微妙に異なっていて、中には 3.x では動作しないものがある。 その多くは 2.x の中でも古いバージョンで使われていたものなんだけど、pylint の --py3k オプションはそれを見つけて警告してくれる。
pylint をインストールする
pylint はサードパーティ製のパッケージなのでパッケージマネージャ (easy_install や pip) を使ってインストールする。
$ pip install pylint
インストールすると pylint コマンドが使えるようになる。 ちなみに --py3k オプションを使う場合、インストール先の Python 実行環境は 2.x じゃないとだめっぽい。
$ pylint --version No config file found, using default configuration pylint 1.4.4, astroid 1.3.8, common 1.0.2 Python 2.7.10 (default, Jul 14 2015, 19:46:27) [GCC 4.2.1 Compatible Apple LLVM 6.0 (clang-600.0.39)]
pylint を使ってみる
それでは早速 pylint の --py3k オプションを使って Python 3 非互換のシンタックスをソースコードの中から見つけてみよう。 次のファイルでは print を文として使ってしまっているため 3.x では動作しない。
$ cat << EOF > sample.py #!/usr/bin/env python # -*- coding: utf-8 -*- def main(): print 'Hello, World!' if __name__ == '__main__': main() EOF
Python 3.4 で実行してみてもエラーになる。
$ python --version Python 3.4.3 $ python sample.py File "sample.py", line 6 print 'Hello, World!' ^ SyntaxError: Missing parentheses in call to 'print'
それでは、このソースコードを pylint にかけてみよう。
$ pylint --py3k sample.py | head No config file found, using default configuration ************* Module sample E: 6, 4: print statement used (print-statement) Report ====== 5 statements analysed. Statistics by type ------------------
目論見通り「print 文が使われてるぞこらー!」とエラーになった。
ちなみに、結構細かい仕様変更でも見つけてくれるみたい。 次のソースコードでは 2.x と 3.x で返り値の型が変更になった '/' 演算子をそのまま使っている。
$ cat << EOF > sample.py #!/usr/bin/env python # -*- coding: utf-8 -*- from __future__ import print_function def main(): print(1 / 1) if __name__ == '__main__': main() EOF
pylint にかけてみよう。
$ pylint --py3k sample.py | head No config file found, using default configuration ************* Module sample W: 8,10: division w/o __future__ statement (old-division) Report ====== 6 statements analysed. Statistics by type ------------------
おおー、「'/' 演算子使うなら future.division をインポートしなきゃダメじゃん!」と警告してくれている。
ツールの限界
ただ、残念ながらチェックできるのはシンタックスレベルまでで、標準ライブラリ周りの変更までは調べきれないようだ。 次のソースコードでは 3.x で名前が異なる標準ライブラリの urlparse モジュールを使っている。
$ cat << EOF > sample.py #!/usr/bin/env python # -*- coding: utf-8 -*- from __future__ import absolute_import from __future__ import print_function from urlparse import urlparse def main(): o = urlparse('http://example.jp') print('netloc: {netloc}'.format(netloc=o.netloc)) if __name__ == '__main__': main() EOF
これも pylint にかけてみる。
$ pylint --py3k sample.py | head No config file found, using default configuration Report ====== 9 statements analysed. Statistics by type ------------------ +---------+-------+-----------+-----------+------------+---------+
残念ながら見つけることはできなかった。
まとめ
今回は pylint を使って Python 3 非互換のシンタックスをソースコードの中から見つけ出すやり方を紹介した。 Python に慣れないうちは、過去のブログ記事などを参考にしたりなんかで意図せず古いシンタックスを使ってしまうようなことがある。 そういうのは指摘してもらわない限りなかなか気づかないもので、いざ必要となったときにげってなるのがありがち。 そうした意味で、Python 3 非互換に限らず推奨されない書き方をしたときに教えてくれる pylint は大変貴重な存在といえる。 元々 pylint はソースコードの品質をチェックするためにかけておくのが基本って感じなので、ついでに --py3k しておくのがいいんじゃないかと思う。

スマートPythonプログラミング: Pythonのより良い書き方を学ぶ
- 作者: もみじあめ
- 発売日: 2016/03/12
- メディア: Kindle版
- この商品を含むブログを見る