- 「ここで改行するほうがキレイで良いと思います」
- 『いや、私はこちらのほうがキレイ良いと思います』
コードレビューでこういう議論をしたことはありませんか? 大切なことだとは思いますが、生産性にはあまり直結しません。議論を避けるために書き方を決めるほうが良いでしょう (個々の問題について逐次議論するのがエネルギーを無駄にしてしまいます。一度決めて、再利用するようにしたいものです)。
今日はそのために使える black というツールを紹介します (「私はflake8を使ってるから結構です」と思われるかもしれませんが、少し違う話なので読んでみてください)。
blackを使おう
Pythonのコードを自動でフォーマットしてくれる black を紹介します。
blackはPythonのコードフォーマッターで、自動的にPythonプログラムの書き方を修正してくれます。 PEP8 というPythonのコードスタイルにも準拠していますので安心です。
Python向けの自動フォーマッターはいくつかありますが、他のフォーマッターとの違いは何でしょうか?一言で言うと、blackはより制限が強いということです。
blackの特徴
Pythonの自動フォーマッターといえば autopep8 や yapf などありますが、blackはより制限が強く、自由に設定ができないのが特徴です。
PEP8では触れられていない、改行の仕方や、シングルクォートとダブルクォートの統一、末尾カンマの統一、余計な丸括弧の削除、数値リテラルの書き方統一などをしてくれます。 私の捉え方としては、blackは「自動フォーマッター」というよりも「制限のきついPEP8」です。
設定できることはせいぜいファイルの幅(文字数)や除外するディレクトリーの設定くらいでしょうか。 開発プロジェクトごとの違いや好みを反映することはほぼできません 。 「うちのプロジェクトはルールで、こう改行するように決めている」というのであれば、改宗するか、諦めるしかありません。 改行位置とかも自動で揃えられるので「ここの論理行はここで改行するのが好き」とかそういうのは無理です。
- PEP8に自動で従ってほしい
- PEP8で触れられてない以上のルールを設定したい
- どこで改行するか議論したくない
\
で改行するか()
で改行するか()
のどこで改行するのか
- シングルクォートを使うのか、ダブルクォートを使うのかで議論したくない
- 「プロジェクトごとに色々設定」できないほうが楽で良い
私個人としてはこの「設定させない」というのは良いと思っています。
ただ「シングルクォートをダブルクォートに統一する」などのblackのルールは正直好みに合いません(私には『シンボル』的な文字列ならシングルクォートを、『文字列』的な文字列ならダブルクォートを使うというマイルールがありまして、そういった美的センスも大切だとは思いますが)。
誰がblackを使っているの?
ココ最近、私の仕事での開発環境を整備していて、black をプロジェクトに導入しました。 Used by を見ると他に使っている人のコメントが読めます。
また、Djangoのソースコード開発ではblackを使うというプロポーザルがアクセプトされています。
ただ、blackはまだ公式には「まだベータだよ」と言っていますので、性急に捉える必要はないでしょう。
2022年2月8日追記:正式リリースされています! black最高!
blackを使おう
blackは単なるコマンドなので、インストールして使うだけです。
pip install black black <target>
blackを設定しよう
基本的にblackにはあまり設定できる項目がありませんが、文字の幅や無視するパスを指定できます。
Pythonのプロジェクト配下に pyproject.toml
をおいて、以下のように書けます。
この例では「1行の文字数は99文字」という設定と、blackの対象にしないディレクトリーを設定しています。
[tool.black] line-length = 99 exclude = ''' ( migrations | .mypy_cache | .pytest_cache | .tox | venv ) '''
書き方はこちらを参照してください。
blackをプロジェクトに導入しよう
既存のPythonのプロジェクトにblackを導入する場合、単に「コマンドとして使う」だけでは不十分です。 プロジェクト内で定期的に実行して、Pythonコードの品質を保つようにしましょう。
オススメの方法は、 tox.ini
やCIで定期的に実行することです。
以下の例は tox.ini
に書いて単体テストとして実行する方法です。
[testenv:black] basepython = python3.7 deps = black commands = black . --check
--check
オプションを付けると「blackの書き方に則ってるかどうか」のチェックだけしてくれます。
他にも --diff
コマンドで差分表示、 --version
でバージョン表示もできるので同時に実行していても良いでしょう。
blackを自動で実行しよう
ただspacemacsは対応中のようです。2019年6月3日現在だとdevelopブランチにはマージされているようです(yapfでなくフォーマッターとしてblackを指定できるようになるようです)。
私はgit の precommitの実行は設定していません。
flake8と共存する
Pythonのプロジェクトであれば flake8 を使っていることと思います。 blackはflake8と併用できますが、併用する場合は一部非互換の部分があるのでちゃんと設定しましょう。
[flake8] max-line-length = 99 ignore = E203,W503,W504
max-line-length
はblackと同じ幅を指定すればOKです。blackはデフォルトで88文字なので、black側で設定しないときはここで88を指定しましょう。
次の ignore
は、flake8とblackで 互換がない点を無視するための設定です。
isortと共存する
Pythonのモジュールインポート順を自動で修正してくれる isort ともblackは共存できます。
blackはインポート順は直さないですが、isortのデフォルトの書き方に文句を言うので設定します。
以下のように pyproject.toml
や tox.ini
に設定すると良いです(例によって行の文字数は99文字に設定しています)。
[tool.isort] include_trailing_comma = true line_length = 99 multi_line_output = 3
これは pyproject.toml
に書いた例です。
細かい話ですが、isortを pyproject.toml
で設定したい場合は pip install isort[pyproject]
でインストールしましょう。
まとめ
blackは
- PEP8より制限のきついルール
- 色々設定できない
- 使いやすい
スペシャルサンクス
aodag さんに実際のプロジェクトでどう使ってるかを色々と教えてもらいました
(上記の --check
オプションについてや、エディターの設定など)。
blackについてはaodagさんのこのトークでも紹介されてます。Pythonのプロジェクトにおいて効率的に開発する方法が説明されてますので参考にしてください。
他のオススメ記事
ぜひTwitterアカウントもフォローしてください!