python

Python, Djangoをきちんと使いたい_05: Flake8 でコーディングルール違反を自動チェック

皆さまこんにちは、ウチイダです。

時間を見つけてはDjango で中規模以上のアプリケーションを開発するための環境構築について調べています。

前回の記事はこちら。

ウチイダの作業環境は以下です。

  • Windows 11 21H2
  • WSL2 Ubuntu20.04
  • GNU bash, version 5.0.17(1)-release (x86_64-pc-linux-gnu)

以降の内容は、この環境にPython/Djangoの開発環境を導入していく手順メモとなります。

PEP 8 遵守はFlake8 におまかせ

さて、前回も述べたとおりですが、コーディングルールを決めたり、目視・手動でルールを順守するのはとても大変です。プログラムを書くときは、ロジックの実装のことだけ考えていたいものです。

PythonにはPEP 8というデファクトスタンダードなスタイルガイドがありますので、これにきっちり合わせていきたいです。

書いたプログラムがPEP 8 のルールに沿っていない場合に教えてくれるのが、Flake8 です。

厳密には、コードチェックのためのいくつかのパッケージを含んでいますが、今回はPEP 8のチェックのために利用します。

パッケージのインストール

過去の記事に続いて、poetry でインストールしていきます。

(python-flake8-sample-py3.11) $ poetry add --dev flake8
Creating virtualenv flake8-sample in /home/y-uchiida/python/flake8_sample/.venv
The --dev option is deprecated, use the `--group dev` notation instead.
Using version ^6.0.0 for flake8

Updating dependencies
Resolving dependencies... (0.2s)

Writing lock file

Package operations: 4 installs, 0 updates, 0 removals

  • Installing mccabe (0.7.0)
  • Installing pycodestyle (2.10.0)
  • Installing pyflakes (3.0.1)
  • Installing flake8 (6.0.0)

CLI から実行する

それではFlake8 を使ってみます。

flake8 <チェック対象のファイルパス> で実行できます。

PEP 8に沿ってない内容のスクリプトを書いて、、、

if 1 is 1:  # リテラルの比較に is は使わない
  print('always true')  # インデントはスペース4つにする

Flake8 で検査します。

(python-flake8-sample-py3.11) $ flake8 flake8_test.py
flake8_test.py:1:4: F632 use ==/!= to compare constant literals (str, bytes, int, float, tuple)
flake8_test.py:2:3: E111 indentation is not a multiple of 4

しっかりエラーを出してくれました!

Flake8 はチェックツールなので、自動での修正はしてくれません。列挙された内容を見て、それぞれ必要な修正をしていきましょう。

VSCode のFlake8 拡張

とはいえ、CLIでコマンドを実行して、それを確認しながら修正するのは大変です。

コードを記述している段階で、エディタ上にエラーが出てくる方が簡単です。

というわけで、VSCodeに拡張機能を導入していきます。

Microsoft が提供している拡張機能があるので、これを利用します。

Flake8 の拡張機能を導入

拡張機能の説明文によると、この拡張機能を導入するだけで、Flake8でのコードチェックが使えるようになるみたいです。

プロジェクトで選択されているPython環境にFlake8 がインストールされていない場合だけ、拡張機能がバンドルしているflake8 (5.0.4)が利用されるとのこと。

CIで利用するにはパッケージを入れておく必要がありますが、書き捨てのちょっとしたプロジェクトなら、拡張機能を入れておくだけでいいかもしれません。

まあ、そういう場合はそもそもコードチェックツール使う必要もないのかもしれませんが…

設定値の変更

念のため、VSCode でFlake8がしっかり動作するように、設定を変更していきます。

まずはデフォルトのリンターを変更します。

デフォルトでPylint が有効になっているので、これを無効にしておきます。

VSCode の設定をひらいて、python.linting.pylintEnabled のチェックを外します。

設定でPylint を無効にする

代わりに、Flake8 を有効にします。

python.linting.Flake8 Enabled にチェックをつけます。

設定でFlake8 を有効にする

これで、基本的にはOKです。

こんな感じで、エディタ上とProblemsパネルにスタイル違反を表示してくれます。

VSCode 上でPEP8 に沿っていない記述がわかる

これで、問題のあるコードがすぐにわかります。

Blackとの併用の設定

さて、ここまででFlake8 の設定自体は終わりです。

しかし、「妥協を許さないフォーマッター」ことBlackと併用する場合、ルールの食い違いが起こってしまいます。

Black はルールの変更ができないので、Flake8 のルールを変更してあげる必要があります。

Black のドキュメントに対応方法が書いてあるので、それに従えばOKです。

https://black.readthedocs.io/en/stable/guides/using_black_with_other_tools.html

設定ファイルとして.flake8 か、setup.cfg か、tox.ini を用意して、以下のように記述します。

すでに上記のファイルがある場合は、追記してください。

[flake8]
max-line-length = 88
extend-ignore = E203

残念ながらFlake8 はpyproject.toml の設定情報を読んでくれません。

pyproject-flake8 という、Flake8 のラッパーを導入することでpyproject.toml に設定を書くことができるようです。

.flake8 ファイルを使えば、Flake8 の設定ファイルであることが一目瞭然なので、あえてこのままでもいいのでは、と考えています。

ちなみに、上記の設定例ではmax-line-length が88になっていますが、1行88文字は意外と短いです。

Blackでも唯一変更できるルールなので、設定値を100とか120に変更する場合もあると思います。

その場合は、Flake8のほうもその設定に合わせておきましょう。

まとめ

PEP8 のさまざまなルールを瞬時にチェックしてくれるFlake8のご紹介でした。

コードスタイルの乱れは風紀の乱れ、ということで、勝手に風紀委員と思っています。

Flake8 には、maccabe というコードの複雑度を判定するパッケージも含まれています。

これも使ってみたいところですが、運用方法がややこしくなりそうなので、今のところは見送っています。

以上です。あなたのお役に立てると嬉しいです。

参考資料

https://qiita.com/fehde/items/723b619013dc86008acc

https://itc-engineering-blog.netlify.app/blogs/black-flake8

Python, Djangoをきちんと使いたい_04: Black を入れてフォーマットをかける

皆さまこんにちは、ウチイダです。

時間を見つけてはDjango で中規模以上のアプリケーションを開発するための環境構築について調べています。

前回の記事はこちら。

ウチイダの作業環境は以下です。

  • Windows 11 21H2
  • WSL2 Ubuntu20.04
  • GNU bash, version 5.0.17(1)-release (x86_64-pc-linux-gnu)

以降の内容は、この環境にPython/Djangoの開発環境を導入していく手順メモとなります。

Blackで、フォーマッターの下の平等を実現する

コードスタイルの一貫性を保つのは、読みやすさを維持するために重要です。でも、コーディングルールをきちんと決めるのがまず大変だったりします。

また、コーディングルールを気にかけながらコードを書くのはつらいです。

こういうのはツールに頼ってしまいたい部分ですね。

今回はBlack を利用して、自動フォーマットをかけるところまでやってみたいと思います。

パッケージの導入

過去の記事に続いて、poetry でインストールしていきます。

$ poetry add --dev black
Creating virtualenv python-black-sample in /home/y-uchiida/develop/python-black-sample/.venv
The --dev option is deprecated, use the `--group dev` notation instead.
Using version ^23.1.0 for black

Updating dependencies
Resolving dependencies... (0.5s)

Writing lock file

Package operations: 6 installs, 0 updates, 0 removals

  • Installing click (8.1.3)
  • Installing mypy-extensions (1.0.0)
  • Installing packaging (23.0)
  • Installing pathspec (0.11.0)
  • Installing platformdirs (3.1.0)
  • Installing black (23.1.0)

これだけでセットアップ完了です!

CLIから実行する

black <修正対象のファイルパス> で、自動フォーマットを実行できます。

こんな感じで、みるからにガタガタなファイルを作って…

def main():	
      print("this"      +      "is"      +      'main')
      return            0

コマンドを実行!

(python-black-sample-py3.11) $ black format_test.py 
reformatted format_test.py

All done! ✨ 🍰 ✨
1 file reformatted.

以下のように修正されました。

def main():
    print("this" + "is" + "main")
    return 0

Black の特徴

基本的な使い方がわかったところで、Black について知っておきましょう。

Blackは、ルールがとても厳格というか、選択の余地がないフォーマッターです。

ドキュメントの冒頭で、こんなことを書いています。

By using Black, you agree to cede control over minutiae of hand-formatting. In return, Black gives you speed, determinism, and freedom from pycodestyle nagging about formatting. You will save time and mental energy for more important matters.

https://black.readthedocs.io/en/stable/

ざっくり意訳すると、Blackが提供するコードスタイルに従うことで、手作業でのフォーマットや、書式設定をしなくてよくなるよ!ということです。

コードスタイルにこだわりがある人はとっつきづらいかもしれませんが、チーム開発では自動で統一されるメリットは大きいですね。

ちなみに、設定ファイルでデフォルトから変更できるルールは、2023年3月時点では1行あたりの文字数だけです。

公式リポジトリのpyproject.toml にも、それしか設定項目がありません。

https://github.com/psf/black/blob/main/pyproject.toml

「妥協を許さないフォーマッター」というだけのことはあります。

VSCode のBlack 拡張機能

次はVSCodeでBlackを利用する場合の設定手順です。

設定といっても、拡張機能をインストールするだけでした。

VSCode用 Black 拡張機能

Black のパッケージをインストールしていなくても、この拡張機能を有効にすればOKです。

preview ってついているのが若干気になりますが、基本的な動作には問題なさそうでした。

拡張機能を入れただけだと、Blackのルールでフォーマットされないので、少しだけ設定を編集します。

@lang:python defaultFormatter で検索すると表示される項目を、Black Formatter に指定します。

Black Formatter をデフォルトに指定

また、 python.formatting.provider のデフォルトがautopep8 になっているので、 black を指定しておきます。

autopep8 から black に変更

また、ファイルの保存時にblack でフォーマットがかかるように、Format On Saveの設定も有効にしておきます。

Format On Save のチェックをオンにする

これで、VSCodeの設定は完了です!

スペースがガタガタなファイルを、VSCode で保存してみると、きっちりそろえてくれます✨

まとめ

導入するだけですぐに使えるフォーマッター、Blackのご紹介でした。

コードスタイル疲れのない、快適なPythonライフを送れそうです。

OSSでの利用数もすごく増えているようで、Blackに慣れておくといろいろなPython のコードが読みやすくなるかもしれません。

以上です。あなたのお役に立てると嬉しいです。

参考資料

https://nobunobu1717.site/?p=1845

https://nujust.hatenablog.com/entry/2022/07/24/114715

Python, Djangoをきちんと使いたい_03: mypy で型安全を得る

皆さまこんにちは、ウチイダです。

時間を見つけてはDjango で中規模以上のアプリケーションを開発するための環境構築について調べています。

前回の記事はこちら。

ウチイダの作業環境は以下です。

  • Windows 11 21H2
  • WSL2 Ubuntu20.04
  • GNU bash, version 5.0.17(1)-release (x86_64-pc-linux-gnu)

以降の内容は、この環境にPython/Djangoの開発環境を導入していく手順メモとなります。

転ばぬ先の型チェック

今回は、型チェッカーを導入します。

TypeScript + React をやり始めてから、実行時エラーで悩むことが激減しました。

Pythonでもそういう開発体験ができるといいなあと思って、型チェッカーを使っていくことにしました。

Pythonでは、TypeScriptのような静的型付けの機能を持ったスーパーセット言語はなさそうですが、型ヒント(Type hinting)が機能としてついているので、これを使うと型不整合を検出できるようです。

型の不整合をチェックするツールとしては、mypy がメジャーなようなので、これを導入していきます。

http://mypy-lang.org/index.html

エラーチェックツールとしては、VSCodeの拡張機能であるPylance も人気があります。

しかし、こちらはあくまでVSCode上でチェックをしてくれるもので、CLIで任意のタイミングに実行することができません。

チーム開発で使うことを考えて、Gitのpre-commitやレビュー実施時にCLIから実行をすることを考えて、mypyを採用します。

おことわり

mypy の導入にあたってはスムーズに行かなくてけっこう試行錯誤しました。

うまくいかない経緯も何らかのお役に立てるかもしれないと思い、なるべくそのまま掲載しています。

シンプルな導入手順を知りたい方にとっては冗長かもしれません。そのうちきれいに手順をまとめようと思います。

mypy のインストール

Poetry で導入する場合の例です。

$ poetry add --group dev mypy
The --dev option is deprecated, use the `--group dev` notation instead.
Using version ^0.991 for mypy

Updating dependencies
Resolving dependencies... (0.3s)

Writing lock file

Package operations: 2 installs, 0 updates, 0 removals

  • Installing typing-extensions (4.4.0)
  • Installing mypy (0.991)

pip でインストールする場合は以下のようにコマンドを実行します。

$ pip install mypy

これだけで導入は完了です。

CLI からチェックを試す

ためしに、あえて型不整合があるスクリプトを書いて、それをチェックしてみます。

import datetime

var: datetime.datetime = "foo"

mypy でのチェックは、mypy <対象ファイル> で行います。

$ mypy mypy_test.py
mypy_test.py:3: error: Incompatible types in assignment (expression has type "str", variable has type "datetime")  [assignment]
Found 1 error in 1 file (checked 1 source file)

datetime と str で型エラーが出ました!

ところで、上記のスクリプトって実行時エラーにもならないんですね…

VS Code 上で警告を表示する

続いて、VS Codeのエディタ上に型不整合のエラーを表示していきます。

VS Code上の設定項目にmypy が入ってるので、これを有効にします。

Mypy Enabled にチェックを入れる

ウチイダこれだけでOKでした。

さらに、プロジェクト全体を自動でチェックしてくれるように、Mypyの拡張機能も導入してみます。

上記の設定だと、ひらいてるファイルのチェックしかしてくれないようなんですよね…

mypy をシステムグローバルにインストールしていない(プロジェクトごとの仮想環境にしかインストールしていない)場合、mypy daemon が見つからない、という警告が出る場合があります。

mypy daemon が見つからないエラー

公式ドキュメントを見てみると、mypy server プロセスを起動させて置きそれに型チェックをさせるしくみがあるようです。

VS Codeはこれと連携して、チェックをしているみたいですね。

https://mypy.readthedocs.io/en/stable/mypy_daemon.html

さらに、mypy の拡張機能の説明文を読んでみると、仮想環境上のmypy を利用する場合は、 mypy.RunUsingActiveInterpreter をEnable にするように、と書いてありました。

仮想環境のmypy を使う場合の指示

設定をしたところ、エラーが消えました!

Dmypy.Executable はデフォルト値のままでOKです。

これで基本の設定は完了です。

返り値の型指定がない関数の内部はチェックされない

基本の設定は完了…と思っていたのですが、まだもう少し続きます。

どんなパターンでエラーが出るのか、いろいろ試していたところ、間違っていそうなのにVS Code で警告されないものがありました。

str 型の変数に、わざわざint キャストした整数値を代入しています。

def main():
    num_string: str = int(2)
    print(f"test: {num_string}")


if __name__ == "__main__":
    main()

それでも、エラーになりません。

エディタ上でも、CLIでもエラーにならない

よく見ると noteのところに、untyped な関数の内部はデフォルトではチェックしないので、 –check-untyped-defs を使ってみて、と書いてあります。

オプションを加えてチェックを再実行したところ、エラーになりました。

–check-untyped-defs オプションをつけるとエラーになる

untyped function というのは、返り値の型を定義していない関数のことのようです。

というわけで、 main() の返り値としてNoneを指定してみます。

返り値を設定したら、エラー検出された

untyped function ではなくなったので、エディタ上でも検出してくれました。

VS Codeでのチェックにオプションを設定する

型注釈がない関数が、VS Code上で警告されないのはつらいです。

調べてみたところ、VS Code の設定から、 mypy のチェックオプションを設定できるようでした。

設定画面を開いて、 python.linting.mypyArgs から設定できます。

ひとまず、–check-untyped-defs を追加しました。

python.lintinh.mypyArgs に –check-untyped-defs を追加

すると、 main() の返り値に型注釈がなくてもエラーを検出してくれました!

unyped-function の内部も、エディタ上で警告されるようになった

mypy のチェックオプション

オプションとして設定できる項目はいろいろあるようです。

https://mypy.readthedocs.io/en/latest/command_line.html#specifying-what-to-type-check

Python の型ヒントの仕様とあわせて理解すれば、良い感じの制限を作れそうです。

VS Code の設定を共有する

VS Code をチームで統一して使っている場合、その動作も統一したくなります。

mypy はけっこう設定の作業項目が多いので、可能なら全員で同じ設定ファイルを共有してしまうのがよいと思います。

プロジェクト内に .vscode/settings.json を作って、Git リポジトリに共有するだけでいいのでお手軽ですね。

mypy の設定は、json でみると今のところこんな感じになっています。

{
  "python.linting.mypyEnabled": true,
  "mypy.runUsingActiveInterpreter": true,
  "python.linting.mypyArgs": [
    "--follow-imports=silent",
    "--ignore-missing-imports",
    "--show-column-numbers",
    "--no-pretty",
    "--check-untyped-defs"
  ]
}

もう少しきちんと設定ファイルを作りたいです。。。

まとめ

とりあえずCLIと、VS Code上での型不整合の検出ができるようになりました。

TypeScriptもそうですが、設定周りで覚えることが多いので、もっと使い慣れていく必要があるなと思いました…

というわけで、今回はここまで。

あなたのお役に立てればうれしいです。

参考資料

https://ohke.hateblo.jp/entry/2020/10/03/230000

https://mypy.readthedocs.io/en/latest/mypy_daemon.html

https://future-architect.github.io/articles/20201223/

https://mypy.readthedocs.io/en/latest/command_line.html#specifying-what-to-type-check

VSCode で、PythonのGotoDefinitionが動かない – Language Serverの設定を見直す

皆さまこんにちは、ウチイダです。

Pythonの環境設定をいろいろ試しているところで、タイトルの事象が発生しました。

VSCodeでは、コード上の変数やクラス名にカーソルを置いてF12を押すと、その定義を開いてくれる機能があります。

その機能がいつの間にか使えなくなっていました。

「定義が見つからない」と表示される

原因:LSPが設定できていなかった

定義へ移動する機能は、LSP(Language Server Protocol)によって実現されています。

詳細はこちらで…

https://github.com/microsoft/language-server-protocol

VSCodeで編集している内容に対して、このLanguage Serverを介して機能を提供する仕組みです。

そのため、Language Serverが動作していないといけないということになります。

通常はVSCode起動時に、指定されたLanguage Serverが起動するようになっているはずです。

そこで、VSCode の設定を確認してみたところ、Python のLanguage Server で「None」が選択されており、を起動しない設定になっていました。

これを「Default」に変更したところ、改善しました。

Mypyを導入する際に既定のLanguage Server であるPylanceと併存できるかいろいろ調べていたので、その時にやってしまったのかもしれません。

原因究明するまでに結構時間がかかってしまいました。

以上です。あなたのお役に立てればうれしいです。

Python, Djangoをきちんと使いたい_02: Poetry でパッケージ管理

皆さまこんにちは、ウチイダです。

Python開発環境を整えるメモ、今回はパッケージ管理の仕組みをやっていきます。

前回はpythonランタイムのバージョン管理のためにpyenv を導入しました。

ウチイダの作業環境は以下です。

  • Windows 11 21H2
  • WSL2 Ubuntu20.04
  • GNU bash, version 5.0.17(1)-release (x86_64-pc-linux-gnu)

以降の内容は、この環境にPython/Djangoの開発環境を導入していく手順メモとなります。

Python のパッケージ管理ツール

公式かつ最大手のpip

パッケージ管理ツールは公式からpip が提供されていますが、どうやら依存解決に難があるようなのです。

pip install しても、composer やnpmみたいに lock ファイルとかできないですしね…

あと、依存解決でインストールされたパッケージが、他からの依存がなくなっても削除されなかったりするようです。

ウチイダは基本的に公式のツールを使っていきたいスタンスですが、これはさすがに不安が残ります。

Pipenv, Poetry, Pyflow

というわけで、ほかの言語のパッケージ管理ツール機能を持ったサードバーティのツールを調べてみました。

Pipenv, Poetry, Pyflow の3つが有力っぽいです。Pipenv が先にリリースされて、そのあとにPoetry、 Pyflow の順番でリリースされています。

いろいろ調べたのですが、タイトルの通りPoetry を使ってみることにしました。

https://python-poetry.org/

比較は今回の趣旨ではないので、ごく簡単に理由を書いておくことにします。

  • PEPで策定されてる形式の設定ファイル(pyproject.toml)ひとつで管理できる方式
  • pyproject.toml が使えるのがPoetry とPyflow
  • Pyflow はまだ安定してないっぽい(バージョン1になってない)

選定が妥当かどうかはわかりません。技術選定の審美眼ほしい。

インストール

# 1. インストール用のスクリプトを読み込んで実行
$ curl -sSL https://install.python-poetry.org | python3 -
Retrieving Poetry metadata

# Welcome to Poetry!

This will download and install the latest version of Poetry,
a dependency and package manager for Python.

It will add the `poetry` command to Poetry's bin directory, located at:

/home/y-uchiida/.local/bin

You can uninstall at any time by executing this script with the --uninstall option,
and these changes will be reverted.

Installing Poetry (1.2.2): Done

Poetry (1.2.2) is installed now. Great!

To get started you need Poetry's bin directory (/home/y-uchiida/.local/bin) in your `PATH`
environment variable.

Add `export PATH="/home/y-uchiida/.local/bin:$PATH"` to your shell configuration file.

Alternatively, you can call Poetry explicitly with `/home/y-uchiida/.local/bin/poetry`.

You can test that everything is set up by executing:

`poetry --version`

# 2. パスが通っていなければ、以下を追加
$ echo 'export PATH="$HOME/.local/bin:$PATH"' >> ~/.bashrc

# 3. poetry が実行できれば完了!
$ poetry --version

Poetry のアップデート

インストールした直後なので不要ですが、未来の自分のためにメモ。

poetry self update で更新します。

$ poetry self update
Updating Poetry version ...

Using version ^1.2.2 for poetry

Updating dependencies
Resolving dependencies... Downloading https://files.pythonhosted.org/packages/d1/20/4c2ea55d6547460a93dce9112599953be1c9Resolving dependencies... Downloading https://files.pythonhosted.org/packages/1d/38/fa96a426e0c0e68aabc68e896584b83ad1eeResolving dependencies... Downloading https://files.pythonhosted.org/packages/76/cb/6bbd2b10170ed991cf64e8c8b85e01f2fb38Resolving dependencies... (25.9s)

Writing lock file

No dependencies to install or update

Poetry のアンインストール

インストールしたばかりなのでこちらも不要ですが、未来の自分のためにメモ。

インストールのコマンドの最後に –uninstall オプションをつけるだけです。削除のためのモードも含めてるんですね。

$ curl -sSL https://install.python-poetry.org | python3 - --uninstall
Removing Poetry (1.2.2)

Poetry でプロジェクトを作る

空のプロジェクトを作るなら、poetry new <プロジェクト名>、

既存のディレクトリに作成する場合はpoetry init です。

# 新しくプロジェクト用のディレクトリを作る場合
$ poetry new porty_new_sample
Created package porty_new_sample in porty_new_sample

# 既存のディレクトリにプロジェクトを追加する場合
$ poetry init

Poerty で仮想環境を作る

Poetry はPythonのバージョン管理こそできませんが、仮想環境を作成することができます。

Python の公式ツールとなったvenv でも仮想環境は作れますが、仮想環境を起動してからスクリプトを実行しないといけないのですこし面倒です。

poetry は、そのCLIから仮想環境のランタイムで指定のスクリプトが実行できるので、開発中のコマンド実行が少し楽になるかもしれません。コマンド実行ごとのタイプ量が増えるので、一長一短かも。

仮想環境の作成先を設定

デフォルトの設定では、Poetryの仮想環境は$HOMEディレクトリ配下の専用ディレクトリに作成されます。

どの仮想環境が実行されているのかわかりづらくなるので、プロジェクトのディレクトリ内にあったほうがいいな…と思います。

というわけで、プロジェクトディレクトリ内に仮想環境が作成されるように、設定をしておきます。

$ poetry config virtualenvs.in-project true

これで、仮想環境は各プロジェクトのディレクトリ内に作成されます。

デフォルトでは.venv というディレクトリ名のようです。

仮想環境を作成・実行する

現在のターミナルで仮想環境に入るときは poetry shell、

仮想環境でコマンドを実行する場合はpoetry run <実行するコマンド>です。

# 仮想環境に入る
poetry_venv_test$ poetry shell
Spawning shell within /home/y-uchiida/poetry_venv_test/.venv
. /home/y-uchiida/poetry_venv_test/.venv/bin/activate
poetry_venv_test$ . /home/y-uchiida/poetry_venv_test/.venv/bin/activate
(poetry-venv-test-py3.11) :poetry_venv_test$

# 出る時はexit (deactivate でもOK)
(poetry-venv-test-py3.11) :poetry_venv_test$ exit

パッケージのインストール

では本題、パッケージのインストールです。

ためしにDhango 3.2 をインストールしてみます。

# パッケージを追加
$ poetry add django==3.2
Creating virtualenv poetry-add-pachage-sample in /home/y-uchiida/poetry_add_pachage_sample/.venv

Updating dependencies
Resolving dependencies... (0.1s)

Writing lock file

Package operations: 4 installs, 0 updates, 0 removals

  • Installing asgiref (3.5.2)
  • Installing pytz (2022.6)
  • Installing sqlparse (0.4.3)
  • Installing django (3.2)

# poetry.lock ができてる!
$ ll
total 28
drwxr-xr-x 5 y-uchiida y-uchiida 4096 Nov 22 16:02 ./
drwxr-xr-x 5 y-uchiida y-uchiida 4096 Nov 22 16:01 ../
drwxr-xr-x 4 y-uchiida y-uchiida 4096 Nov 22 16:02 .venv/
-rw-r--r-- 1 y-uchiida y-uchiida    0 Nov 22 15:42 README.md
-rw-r--r-- 1 y-uchiida y-uchiida 2131 Nov 22 16:02 poetry.lock
drwxr-xr-x 2 y-uchiida y-uchiida 4096 Nov 22 15:42 poetry_add_pachage_sample/
-rw-r--r-- 1 y-uchiida y-uchiida  356 Nov 22 16:02 pyproject.toml
drwxr-xr-x 2 y-uchiida y-uchiida 4096 Nov 22 15:42 tests/

poetry.lock の中身は長いので載せませんが、テキストファイルになっているので普通に読めます。

[[package]] と [package.dependencies] がセットになって、依存関係を表現しているようです。

Poetry にタスク実行機能はないのか

さて、ここまでくると、開発中に利用できるタスクランナーの機能が欲しくなってきます。

結論から言うと、Poetry はタスクランナーの機能は付いていません。

poetry run でそういうことができないのか調べてみたのですが、どうも目的が違うようです。

別のツールを使うか、Makefileなどでショートハンドを作ったりするのがよさそうです。

まとめ

今回はPoetry を利用してパッケージの依存関係ができるようにしてきました。

ウチイダはとても便利だと思ったのですが、公式の強さか、最も利用されているのはpipのようです。

依存関係が管理できないとなんだか不安なのは、Node.js やPHP での経験があるからこそでしょうか…

いずれにしても、効率的なチーム開発にはあったほうがよいでしょうし、導入している例も結構多いようなので、触っておいて損はないかなと思います。

以上です。あなたのお役に立てればうれしいです。

Python, Django をきちんと使いたい 01: Pythonのバージョン管理のためにpyenv を導入【Win11/WSL2-Ubuntu】

皆さまこんにちは、ウチイダです。

Python/Djangoの案件にかかわることになりそうで、改めて勉強しなおそうと思っています。

Djangoはチームの開発で使ったことがなかったので、これを機に周辺ツールの知識もまとめておくことにしました。

ウチイダの作業環境は以下です。

  • Windows 11 21H2
  • WSL2 Ubuntu20.04
  • GNU bash, version 5.0.17(1)-release (x86_64-pc-linux-gnu)

以降の内容は、この環境にPython/Djangoの開発環境を導入していく手順メモとなります。

まずはPythonのバージョン管理ツールから

何はともあれ、ランタイムのバージョン管理を入れることにします。

Node.js のnodenv やvolta とか、PHP のphobrew みたいなものを探してみます。

調べたところ、pyenv がよくつかわれているようです。

https://github.com/pyenv/pyenv

anyenv にも含まれているツールです。rbenv をフォークしてPython 用にしたものだとのこと。

メンテナンスも継続されてるようなので、pyenvを使うことにしました。

インストールする

未来の自分が別の環境でコピペ利用できるように、なるべく汎用的なやり方にしておきます。

GitHubのREADMEに情報がまとまっているので、これに沿って進めれば大丈夫そうです。

https://github.com/pyenv/pyenv#basic-github-checkout

GitHub のリポジトリをクローンする方法で進めます。

READMEに書いてあるのそのままですが、実行するコマンドと出力結果例は以下です。

以下のコマンドをコピペで大丈夫だと思うのですが、いくつか留意すべき点があります。

# 1. リポジトリをclone する
$ git clone https://github.com/pyenv/pyenv.git ~/.pyenv
Cloning into '/home/y-uchiida/.pyenv'...
remote: Enumerating objects: 22214, done.
remote: Counting objects: 100% (282/282), done.
remote: Compressing objects: 100% (154/154), done.
remote: Total 22214 (delta 141), reused 237 (delta 112), pack-reused 21932
Receiving objects: 100% (22214/22214), 4.49 MiB | 4.40 MiB/s, done.
Resolving deltas: 100% (15003/15003), done.

# 2. 高速化のためのBash拡張のコンパイル(やらなくてもOK)
$ cd ~/.pyenv && src/configure && make -C src
make: Entering directory '/home/y-uchiida/.pyenv/src'
gcc -fPIC     -c -o realpath.o realpath.c
gcc -shared -Wl,-soname,../libexec/pyenv-realpath.dylib  -o ../libexec/pyenv-realpath.dylib realpath.o
make: Leaving directory '/home/y-uchiida/.pyenv/src'

# 3-1. ~/.bashrc にpyenv の設定を追加(pyenv がデータを保存するディレクトリを指定)
$ echo "#setting for pyenv" >> ~/.bashrc
$ echo 'export PYENV_ROOT="$HOME/.pyenv"' >> ~/.bashrc
$ echo 'command -v pyenv >/dev/null || export PATH="$PYENV_ROOT/bin:$PATH"' >> ~/.bashrc
$ echo 'eval "$(pyenv init -)"' >> ~/.bashrc

# 3-2. 同じ内容を、 ~/.bash_plofile にも追加する
$ echo "#setting for pyenv" >> ~/.bash_profile
$ echo 'export PYENV_ROOT="$HOME/.pyenv"' >> ~/.bash_profile
$ echo 'command -v pyenv >/dev/null || export PATH="$PYENV_ROOT/bin:$PATH"' >> ~/.bash_profile
$ echo 'eval "$(pyenv init -)"' >> ~/.bash_profile

# 4. 設定を読み込み
$ source ~/.bashrc

# .5 pyenv が実行できれば完了!
$ pyenv -v
pyenv 2.3.6-15-g13d85686

補足・留意点

1. Bash 設定ファイルについて

上記コマンドの中で、.bashrc と.bash_profile にpyenv の設定を追加していますが、READMEによると$HOMEにあるbashの設定ファイル全部に書いとくと安心、とのことです。

ウチイダは自身の$HOME ディレクトリに上記の2つだけしか存在してなかったので、これだけ設定しています。

人によっては .profile とか、.bash_login があるかもしれないので、その場合は同じように追記しておくとよさそうです。

2. $BASH_ENV 環境変数について

$BASH_ENV が .bashrc に設定されてる場合の注意点が記載されてます。

この場合、eval “$(pyenv init -) を .bashrc に記述しておくと、pyenv が無限ループを起こしてしまうとのこと…

echo $BASH_ENV で設定値を確認して、もし.bashrc になっていたら、eval の行は .bashrc から取り除いておきます。

pyenv でPythonをインストール

いくつかの罠を越えてpyenv をインストールできたら、さっそく使っていきましょう。

# 1. インストール可能なバージョンの一覧を表示
$ pyenv install --list
Available versions:
  2.1.3
  2.2.3
  2.3.7
  2.4.0
# ... 以下略

# 2. バージョンを指定してインストール(3.10.x)
$ pyenv install 3.10
Downloading Python-3.10.8.tar.xz...
-> https://www.python.org/ftp/python/3.10.8/Python-3.10.8.tar.xz
Installing Python-3.10.8...
Installed Python-3.10.8 to /home/y-uchiida/.pyenv/versions/3.10.8

# 3. デフォルトで動作するバージョンを設定
$ pyenv global 3.10
$ python --version
Python 3.10.8

# 4. 現在のディレクトリで動作するバージョンを指定
$ pyenv local 3.10

pyenv local は、実行したディレクトリに.python-version というファイルを作って、そこに利用するバージョンを書き込んでいます。

.python-version ディレクトリ階層をみて、直近の上位ディレクトリの.python-version に記載されたバージョンを使ってくれます。

そのほかの使い方は、pyenv –help を実行すると詳しく出てきます。

まとめ

pyenv を導入して、バージョン切り替えできるようにしました。

これで万が一、複数バージョンが必要になった場合も安心です。

それにしても、Pythonってサポート期間長いんですね…どのバージョンも5年ある…

ライブラリも、過去バージョンのサポートを長めに続けているようなので、意外とプロジェクトごとに厳密にバージョン分けする機会ってないのかも…と感じてます。

本当にきっちりやるなら、Dockerとか仮想マシン使うでしょうし…

とはいえ、pythonに限らないですが、OSの公式リポジトリだと最新バージョンをインストールできない場合も多いです。

気軽に最新バージョンに追従できるようにしておくのは悪くなんじゃないかと思います。

以上です。あなたのお役に立てればうれしいです。