はじめに
楳図かずお先生なくして、アイの歌声を聴かせてなし。ご冥福をお祈りします。
nikkieです。
Pythonコミュニティで広く採用されているコーディング規約に沿ったPythonスクリプトを書きたい方に捧げます。
目次
- はじめに
- 目次
- この記事のきっかけ
- PEP 8 – Style Guide for Python Code
- フォーマッタでPEP 8のスタイルを適用する
- Ruffを開発環境にどのように組み込むか
- 終わりに
この記事のきっかけ
Kanonさんからの質問がきっかけでした。
@ftnext
— Kanon (@ysknsid25) 2024年10月27日
ちょっとPythonのこと教えてほしいです🙏
Pythonのコードのお作法的なことを学びたいんですが、良さげなドキュメントとか本ってあるでしょうか?…
このスレッドの内容について、加筆する形で現時点の私の考えを書いていきます。
Pythonのスクリプト1を書いている方が、スタイルガイドに沿うようにするための具体的な方法です。
なお、KanonさんはRuffをVS Code拡張で実行する形にたどり着いたそうです。
ref: じぶん Release Note (ver 2.10.5)|Kanon
PEP 8 – Style Guide for Python Code
PEPは「Python Enhancement Proposal」の略です。
用語集より
https://docs.python.org/ja/3/glossary.html#term-PEP
PEP は、Python コミュニティに対して情報を提供する、あるいは Python の新機能やその過程や環境について記述する設計文書です。
PEP 8がPythonコードのスタイルガイドです。
スタイルとは「見た目」です。
別にPEP 8のスタイルにしなくてもPython処理系としては動きます。
なので、見た目は開発者のためのもの2であり、PEP 8が1つのガイドラインを示しているという理解です。
PEP 8は多岐にわたりますが、その一部をご紹介
開発中のコーディング規約としてPEP 8を採用することが多いかなと思います。
私の経験した範囲では、規約がない(みんな好きに書く6) or PEP 8を採用する(ツールで自動的に適用する)ですね。
フォーマッタでPEP 8のスタイルを適用する
PEP 8をコーディング規約に採用したとき、開発者が気をつけるだけでは限界があります。
PEP 8には非常にたくさんの項目があり、私は全部を覚えているわけではありません。
ではどのようにPEP 8に沿ったPythonコードを書いているかというと、Pythonは好きに書いて、最後にツールでスタイルをPEP 8に合わせます。
このツールがフォーマッタです。
Black
The Uncompromising Code Formatter(妥協なきコードフォーマッタ)
Black以前にもフォーマッタは(いくつも)存在していました。
Black以前のフォーマッタは、PEP 8の中から採用する項目を設定して適用していたと聞いています。
なので、PEP 8をコーディング規約に採用したプロジェクトと言っても、コードのスタイルは異なることがあったそうです。
Blackが革新的だったのは、設定できなくしたこと。
"妥協がない"のです。強制的にPEP 8準拠!!
当時の私はPEP 8の項目を全然知らなかったので、「設定せずに使えるBlackはかえって簡単でいいな」と採用しました。
Black自体もコミュニティに受け入れられたと見えています(リポジトリがPSF下に移管されるまでに。Google発じゃなかったかな?)
なお、Blackだけでは手の届かない箇所が存在しており、他のフォーマッタと一緒に使う必要がありました7。
import順の並び替えはisort、また、不要なimport文の削除はautoflakeです。
Ruff
2023年くらいからPythonのフォーマッタの状況が変わってきているように感じます。
きっかけはRuffの登場。
RuffはRust製で、Astral社が開発しています(後にuvを爆誕させたり、Ryeが移管されたりした会社です)。
Ruffの特徴は、Black、isort、autoflakeとツールの組合せに対して、Ruff 1つで済むというスタンスをとったこと。
現在Pythonで静的コード解析やフォーマットに使われるツールが複数あり、それぞれが構文解析をしているため、もっと効率よくできるのでは?
Ruffは1回の処理で目立ったパフォーマンスの低下なく、すべてのチェック・自動修正が行われることを目標の1つにしています。
Ruffのフォーマットは2つのコマンドを走らせると理解しています
ruff format:Blackのようなフォーマッタが走るruff check --fix --extend-select I:実行しているのはリンター- リンターが検出したルール違反のうち、自動で直せるものは直すのが
--fix(例:autoflakeのような、使われていないimportの削除) - さらに
--extend-select Iとimportのルール(: I) を追加する(isortのフォーマットも適用される)
- リンターが検出したルール違反のうち、自動で直せるものは直すのが
Ruffを開発環境にどのように組み込むか
現在のところ、私はフォーマッタとしてはRuffをオススメしています。
Ruffという存在がある今、Pythonのフォーマッタを初めて使う方に、「Blackとisortとautoflakeと」って伝えるのはハードル高すぎるんじゃないかと思うんですよね。
それでは、開発中にどのように使っていくかを考えてみます。
VS Code拡張として使う
この記事を書くにあたって知ったのですが、便利そうでした。
ファイルを保存した(またはフォーカスが別に移った)ときに、ruff formatもruff check --fixも実行されている印象です
コマンドラインから実行
VS Code拡張を知る前は、uvx ruff(またはpipx run ruff)で使うのがよいと考えていました。
uv8(またはpipx9)をインストールする必要がありますが、これらのツールが最新のRuffを管理して実行してくれます10。
(Ruffは1つの統合コマンドを計画中とのことですが、)現在は2つのコマンドを実行する必要があるので、私はmake devの1コマンドで済むようにMakefileを書いています(Ruffのところで挙げた拙記事を参照)
終わりに
手元のPythonスクリプトをスタイルガイド(PEP 8)に合わせる方法について、現時点の私の考えを書きました。
- Ruffを採用
- Ruffの登場前はBlackやisortなどの組合せが使われていたが、Ruffがある今、組合せるアプローチは最初にオススメしづらい
- エディタの拡張でRuffを実行できるなら、それを使うとよいのでは(例:VS Code)
- (エディタが対応していないなどで)コマンドラインから実行する場合は、
ruff formatとruff checkの2つのコマンドを実行
今回はスクリプトという点でまとめており、プロジェクト(複数ファイル)になるとHatch11が代わりの候補かなあと思います。
HatchはRuffを採用しており、hatch fmtという1コマンドにまとめてくれています。
Ruffをコマンドラインから実行するときの煩雑さを吸収してくれていますね。
ただスクリプトしか書かない状況では、Hatchには使わない機能が多すぎるので紹介しづらいところがあります。
- 「1ファイル、かつ、配布しない」という意味で使っています ↩
- 具象構文12(見た目)と抽象構文という語もありますね。前者は開発者にとって重要で、後者は処理系にとって重要なのかな↩
- https://peps.python.org/pep-0008/#tabs-or-spaces↩
- https://peps.python.org/pep-0008/#whitespace-in-expressions-and-statements↩
- https://peps.python.org/pep-0008/#imports↩
- Webアプリではあんまりないかもしれませんが、データサイエンスプロジェクトだと起こりがちです。参考 https://ytknzw.github.io/StaPy/%E3%83%87%E3%83%BC%E3%82%BF%E3%82%B5%E3%82%A4%E3%82%A8%E3%83%B3%E3%82%B9%E3%81%AE%E3%81%9F%E3%82%81%E3%81%AE%E3%83%AA%E3%83%BC%E3%83%80%E3%83%96%E3%83%AB%E3%82%B3%E3%83%BC%E3%83%89%E3%81%AE%E3%82%B9%E3%82%B9%E3%83%A1_%E3%81%BF%E3%82%93%E3%81%AA%E3%81%AEPython%E5%8B%89%E5%BC%B7%E4%BC%9A_20210113.pdf ↩
- こんな工夫をしてみたり ↩
- Installation | uv↩
- Installation - pipx↩
- 参考(この記事はpipx runについてで、uvxもおそらく同じだと思うんですが未確認で私言っちゃってます) ↩
- 現時点のuvとHatchの差の1つが、フォーマット用コマンドがあるかないかだと思います↩
- 具象構文のフォーマットの一例 ↩