🐹

【2024年版】めっちゃ使いやすいPythonの開発環境をVSCode上で構築する方法

筆者はPythonのパッケージ管理ツールとしてpip、バージョン管理ツール(仮想環境)としてpyenv / virtualenvを利用していますが、
要求されるパッケージのバージョンが衝突する、全体の環境が汚れていくなど色々不便さを感じています。このような悩みはPythonユーザーあるあるではないでしょうか?
そこで今回は、2024年時点で非常に使いやすいと噂のRyeやその他ツールを改めて導入し、
各ツールの利用方法や使い心地などを確認することにしました。

この記事によってできること

  • Pythonの新規プロジェクト立ち上げが容易に行える
    • パッケージ管理、バージョン管理、仮想環境管理を単一のパッケージで行える
  • Pythonのコードに対して思い通りのコーディング規約を定義でき、規約通りに自動修正が入れられるようになる
  • その他、エラー表示などが分かりやすくなり開発体験が向上する

導入

パッケージ管理 / バージョン管理 / 仮想環境管理

Ryeとは

  • Pythonのパッケージ管理 / バージョン管理 / 仮想環境周りの管理がこれ1つで行えるツール
    • 要するに取り回しが楽でめっちゃ使いやすい(はず)です
  • Rust製なので高速で動作します
  • "Rye is still a very experimental tool":「まだ試験的なツールなのでドキュメントの不足や予期しない問題が発生する可能性があるかもしれない」とのこと

導入

  • 環境
    • Ubuntu 22.04 LTS
    • bashを利用
  • 手順
    • curlする
      • curl -sSf https://rye.astral.sh/get | bash
      • 対話型で進行し、質問内容は下記
      • 質問 + 回答例
        1. 入れるRyeのバイナリは問題ないか → yes
        2. パッケージ・インストーラーを選択 → uv (quick but experimental)
        3. RyeでPythonを管理するか → Make Rye's own Python distribution available
        4. どのPythonバージョンをデフォルトにするか → Enterで推奨バージョンが入ります
        5. RyeのPATHを.profileに追加するか →(今回の場合多分どっちでもよいですが)yes
    • PATHを通す
      • echo 'source "$HOME/.rye/env"' >> ~/.bashrc
      • exec bash
    • Shellの補完スクリプトを入れる
      • mkdir -p ~/.local/share/bash-completion/completions
      • rye self completion > ~/.local/share/bash-completion/completions/rye.bash
    • Rye自体をアップデートする
      • rye self update

Linter / Formatter

従来はLinter:Flake8、Formatter:autopep8を利用していましたが、これもRuff1つに統合することにしました。
Ruffは上記のRyeに同梱されているので特段インストール等しなくてもコマンド実行で動いてくれるのですが
今回はVSCode側でいい感じにしてくれるよう、ファイル保存時にフォーマットする+その他諸々の設定を追加します。

  • 手順
    • VSCode拡張機能のRuffをインストール
    • VSCode上でCtrl + Shift + P → > settings ubuntu等入力しsettings.jsonを展開
    • 下記を記載する
settings.json
{
    "[python]": {
        "editor.formatOnSave": true,
        "editor.defaultFormatter": "charliermarsh.ruff",
        "editor.codeActionsOnSave": {
            "source.fixAll": "explicit",
            "source.organizeImports": "explicit"
        }
    },
    "ruff.lint.args": [
        "--config=ruff.toml"
    ],
    "ruff.format.args": [
        "--config=ruff.toml"
    ]
}
  • settings.jsonと同じディレクトリにruff.tomlを作成し下記を記載する
    • 設定は完全にお好みなので適宜調整してください
ruff.toml
# 一般的に無視されるディレクトリを除外
exclude = [
  ".bzr",
  ".direnv",
  ".eggs",
  ".git",
  ".git-rewrite",
  ".hg",
  ".mypy_cache",
  ".nox",
  ".pants.d",
  ".pytype",
  ".ruff_cache",
  ".svn",
  ".tox",
  ".venv",
  "__pypackages__",
  "_build",
  "buck-out",
  "build",
  "dist",
  "node_modules",
  "venv",
]

# 1行の長さの許容上限とインデント幅を設定
line-length = 150
indent-width = 4

# 適用される最低のPythonバージョン
target-version = "py38"

[lint]
# Enable Pyflakes (`F`) and a subset of the pycodestyle (`E`)  codes by default.
# Unlike Flake8, Ruff doesn't enable pycodestyle warnings (`W`) or
# McCabe complexity (`C901`) by default.
ignore = ["ANN", "ERA001", "T201", "FBT003", "G004", "RUF100", "E741", "E70"]
select = ["ALL"]

# ルール修正許可 (`--fix` オプション指定時)
fixable = ["ALL"]
unfixable = []

# underscoreがprefixの際に未使用変数を許可
dummy-variable-rgx = "^(_+|(_+[a-zA-Z0-9_]*[a-zA-Z0-9]+?))$"

[format]
# インデントのスタイルとクオーテーション設定
indent-style = "tab"
quote-style = "double"

# 末尾のカンマ設定
skip-magic-trailing-comma = false

# 行末の検出設定
line-ending = "lf" # "auto" | "lf" | "cr-lf" | "native"

型チェッカー

mypyを使います。
これもVSCodeから見るために拡張機能を入れます。

  • 手順
    • VSCode拡張機能のMypy type checkerをインストール
    • settings.jsonに追記
      • こちらも設定はお好みで変更してください
        • 今回は関数の引数と返り値に型定義がないことを許容しないとしています
settings.json
"mypy-type-checker.args": [
    "--disallow-untyped-defs"
]

テストツール

pytestを使います。
※ 今回の記事では動作の確認等はしていませんが導入のみご紹介します。

その他

エラー箇所と内容が分かりやすくなるようError Lensを導入します。

整備したツール類を使ってみる / 使い方

  • 指定ディレクトリに移動しプロジェクトを開始する
    • 今回、画像のぼかしを取り除く機能の作成で実験
terminal
$ rye init image_sharpening
success: Initialized project in /path/to/dir/image_sharpening
Run `rye sync` to get started 
  • すると下記のような構成のディレクトリができる
tree
image_sharpening
├── .gitignore
├── .python-version
├── README.md
├── pyproject.toml
└── src
    └── test
        └── __init__.py
  • pyproject.tomlauthorsにGitのconfigファイルで設定済みのemailアドレスがデフォルトで記載されてしまうため、嫌な人は変更する
  • project_nameディレクトリに移動し、必要であればPythonのバージョンを変更する
terminal
$ rye pin 3.11
pinned 3.11.9 in /path/to/dir/image_sharpening/.python-version
  • ここまで終わったら一度設定を同期する
terminal
$ rye sync
Downloading cpython@3.11.9
Checking checksum
Unpacking
Downloaded cpython@3.11.9
Initializing new virtualenv in /path/to/dir/image_recognition/image_sharpening/.venv
Python version: cpython@3.11.9
Generating production lockfile: /path/to/dir/image_recognition/image_sharpening/requirements.lock
Generating dev lockfile: /path/to/dir/image_recognition/image_sharpening/requirements-dev.lock
Installing dependencies
    Built file:///path/to/dir/image_recognition
    image_sharpening_20240611
        Built 1 editable in 218ms
Installed 1 package in 0.44ms
    + image-sharpening-20240611==0.1.0 (from file:///path/to/dir/image_recognition/image_sharpening)
Done!
  • 必要なパッケージ類を追加していく
    • 追加後は設定反映を行うために$ rye syncを実行する
    • 特定のformatterを入れる場合など開発用パッケージの追加はオプションとして--devをつける
terminal
# numpyを追加する場合
$ rye add numpy
Added numpy>=1.26.4 as regular dependency
Reusing already existing virtualenv
Generating production lockfile: /path/to/dir/image_recognition/image_sharpening/requirements.lock
Generating dev lockfile: /path/to/dir/image_recognition/image_sharpening/requirements-dev.lock
Installing dependencies
    Built file:///path/to/dir/image_recognition/image_sharpening   
    Built 1 editable in 202ms
Resolved 1 package in 5ms
Downloaded 1 package in 1.15s
Uninstalled 1 package in 0.40ms
Installed 2 packages in 12ms
  - image-sharpening-20240611==0.1.0 (from file:///path/to/dir/image_recognition/image_sharpening)
  + image-sharpening-20240611==0.1.0 (from file:///path/to/dir/image_recognition/image_sharpening)
  + numpy==1.26.4
Done!

<略>

# 設定の反映
$ rye sync
Reusing already existing virtualenv
Generating production lockfile: /path/to/dir/image_recognition/image_sharpening/requirements.lock
Generating dev lockfile: /path/to/dir/image_recognition/image_sharpening/requirements-dev.lock
Installing dependencies
Audited 13 packages in 3ms
Done!  
  • この例の場合では、以前別環境で利用していたパッケージを再利用したようなログが表示されているが問題ない(はず)
  • 仮想環境に入る
    • コマンドは$ source ./.venv/bin/activate
    • 仮想環境に入らずPython実行する場合は$ rye run python hoge.pyで実行可能
      • なのであまり手動で仮想環境に入る必要はないかもです
  • (順序が前後するがテスト用Pythonのコードを書いて)色々確認してみた

codeimage_before
保存前
codeimage_after
保存後
linterで怒られたところはformatterで直してくれているし型チェックも動いていますね。

  • 結果
    • (簡単に実装しています)
sharpen_image.py
import cv2
import numpy as np

input_path = "/hoge/foo/imgrec_dev/20240611_image_sharpening/input/test_blur.png"
output_path = "/".join(input_path.split("/")[:-2]) + "/output/" + input_path.split("/")[-1].split("_")[0] + "_sharpen.png"

kernel = np.array([[-1, -1, -1, -1, -1], [-1, -1, -1, -1, -1], [-1, -1, 25, -1, -1], [-1, -1, -1, -1, -1], [-1, -1, -1, -1, -1]], np.float32)

img = cv2.imread(input_path)

img_sharpen = cv2.filter2D(img, -1, kernel)

cv2.imwrite(output_path, img_sharpen)
print(f"result saved : {output_path}")

test
元の画像

test_blur
ぼかした画像

test_sharpen
ぼかしを取り除いた後

微妙に改善されているのがお判りでしょうか?

まとめ

  • Ryeにはいくつか難点がありますが、それを超えて余りあるメリットを感じます。気になる方は是非使ってみてください!
    • まだまだ紹介出来ていない&筆者も使いこなせていない便利機能がたくさんあります。
  • 自動校正も色々設定でき、かつ高速に動作してくれるのでストレスフリーです。
  • 大事な書類を隠したいときはぼかしではなくモザイクか塗りつぶしをしましょう。

参考資料

今回の記事を作成するにあたり以下の記事を参考にさせていただきました。この場を借りてお礼申し上げます。


フォルシアでは現在、AI画像認識システムの開発ならびに導入支援サービスを展開しております。
気になる点や課題感等ございましたら、是非お気軽にフォームよりお問い合わせください。

サービスご紹介ページ
お問い合わせフォーム


この記事を書いた人

太田 圭祐
2023年キャリア入社 エンジニア
Python周りのツールってやたら「なんとかpy」とか「pyなんとか」が多くないですか?

FORCIA Tech Blog

Discussion