今回の社員ブログのテーマは「Pythonのコード整形ツールをいろいろ使ってみた」です。弊社ではプログラミングの書籍を多数制作しています。書籍に使うサンプルコードを作る機会もあり、私はPythonのサンプルコードを作ることがよくあります。その際、意識する必要があるのはコードの読みやすさです。
PythonにはPEP8というコーディング規約が公開されています。コーディング規約とはコードを記述する際のルールのことです。たとえば、PEP8では「インデントには半角スペース4つを使用する」「1行の長さは最大79文字」といったルールが定められており、このルールに則ると「読みやすくわかりやすいコード」を実現しやすくなります。
そのため、書籍のサンプルコードも、基本的にはこのPEP8を意識して作っています。ただし、このPEP8に則っているかを目視でチェックして直すのは、とても手間がかかります。その際に必要となるのが、コードのチェックや整形を自動化するツールです。
Pythonには、コードのチェックや整形にかかわるツールが多数あり、初心者には情報がわかりづらい面があるので、今回整理してみようと思いました。ここでは、コードのチェックを行うツールと、コードの整形を行うツールについて、それぞれ紹介します。なお、私は基本的にVisual Studio Codeを使用しているので、以下に掲載したのはVisual Studio Codeでの動作結果です。
リンターとは、コードを実行しなくても、そのコードのスタイルに問題がないか、エラーがないかといったことをチェックしてくれるものです。Pythonの代表的なリンターには、Pylintやflake8があります。
Pylint(https://github.com/PyCQA/pylint)は古くからあるツールで、Visual Studio Codeでは、Pylintがデフォルトで設定されています。検証したところ、後述のflake8より、少々厳しい基準が設けられているように感じました。実行するとコードの点数が出て、前回の点数との比較も出るのは、面白いポイントです。
ここでは以下のサンプルコードを使います。このコードに対してPylintを実行してみましょう。
上記のコードでPylintを実行した結果は以下です。
今回の実行結果では、10点満点中0.83点でした。インデントが半角スペース4つになっていない、未使用の変数があるといった点だけではなく、キャメルケースで命名されている変数や、プログラムや関数の1行目に説明用のコメントがないといった点も検出されます。キャメルケースや説明用コメントについてはflake8では検出されないのと、実行結果の行数も多く出ているので、少々細かくチェックされている印象があります。
flake8(https://gitlab.com/pycqa/flake8)は、コードのチェックを行う以下のライブラリのまとめたもの、つまりはラッパーです。
pycodestyleはコードスタイルに関するチェックを行い、PyFlakesは未使用の変数の有無といったエラーに関するチェックを行います。そのためflake8を使うと、それぞれのライブラリの結果を一度に取得できます。
上記のコードでflake8を実行した結果は以下です。
インデントが半角スペース4つになっていない、未使用の変数があるといった点はPylintと同様に検出されています。またPylintでは検出されなかった「関数の間が2行空いていない」「演算子の前後のスペースが開いていない」といった点が検出されました。
リンターはあくまでエラーのチェックをするだけでコードの整形はしません。対してコードフォーマッターは、エラーのチェックではなくコードの自動整形を行うツールです。Pythonにおける代表的なツールには、autopep8やblackがあります。
autopep8(https://github.com/hhatto/autopep8)は、古くからあるコードフォーマッターです。あくまでPEP8に準拠しており、1行の長さはPEP8準拠の79文字、演算子の前後の半角スペース挿入は、演算子の片側に半角スペースがあった場合は挿入するといった動作をします。カスタマイズは可能で、たとえばインデントを半角スペース4つから2つに変更できます。
上記のコードをautopep8で整形した結果は以下です。
black(https://github.com/psf/black)は、近ごろ人気が高いツールです。カスタマイズがほとんどできないという特徴があります。カスタマイズができないというと不便に感じるかもしれませんが、blackに従えばOKというルールにできるので、プロジェクトごとにルールを考える必要がなくなります。blackの特徴的なルールで主なものは以下です。
上記のコードをblackで整形した結果は以下です。
個人的には、Pylintが少々細かすぎるかなと感じたのと、blackだと文字列が” ”囲みになってしまうのがすこし気になったので、flake8とautopep8の組み合わせがよいと思いました。ただ、blackの「カスタマイズができない」という特徴はとてもいいなと感じます。すこし毛色は違いますが、RubyのフレームワークであるRuby on Railsの「ルールに則っとればある程度は自動でやりますよ」という考え方を初めて知ったときを思い出しました。実際の開発現場や大人数のプロジェクトでblackを導入すると、コードのルールをどうするかといった議論を無くすことができ、コードレビューの負荷も軽減できそうです。
コードの読みやすさというのは永遠の課題なので、今後もリンターやコードフォーマッターの動向を追っていきたいと思います。