Python による開発ワークフローを簡素化する:nox 自動化ツールの実践ガイド

Nox とは何か

Python プロジェクトのテストやコードチェックを効率的に管理するためのタスクランナーがノックス(nox)です。これは類似のツールである tox や Make の代替として機能し、複数の Python バージョンでの動作確認や環境構築の自動化が可能です。

インストール手順

最も一般的な導入方法は Pip を介して行うことです:

python3 -m pip install nox

システム全体への影響を抑えたい場合は、ユーザー専用サイトへのインストールを検討できます:

python3 -m pip install --user nox

より洗練された管理を望むなら、PipX も選択肢の一つです:

pipx install nox

一般的に、Nox は他の CI ツールと同様にグローバルに使用されます。Docker コンテナ上で稼働させる必要がある場合は、公式ミラーイメージを使用可能です。また、GitHub Actions などのクラウドインテグレーション環境においても、専用のアクションを使用して最新のバージョン設定を行うことが推奨されています。

構成ファイルの作成

Nox はプロジェクトルートに配置されたnoxfile.pyという Python ファイルで設定を行います。このファイル内には、セッションと呼ばれる処理単位を定義します。セッションは仮想環境とそこに実行されるコマンドセットから成り立っています。

セッション宣言にはデコレータを用います:

import nox

@nox.session
def my_task(session):
    pass

初回の実行

設定が完了したら、ターミナルでプロジェクトディレクトリを開き以下を実行してください:

nox

これにより、定義されたすべてのセッションが順番に起動され、結果が出力されます。ログには仮想環境の作成プロセスやインストール状況、およびコマンド実行の結果が含まれます。

依存関係の管理

ノックスの環境内でパッケージをインストールする際は、標準的な Pip の振る舞いを利用できます。具体的な例としては以下の通りです:

単一または複数パッケージの追加

@nox.session
def run_tests(session):
    # pip install pytest numpy の操作と同じ
    session.install("pytest", "numpy")
    session.run("pytest")

Requirements ファイルからの導入

@nox.session
def build_env(session):
    # pip install -r requirements.lock の操作と同じ
    session.install("-r", "requirements.lock")

プロジェクト自体のインストール

現在の作業ディレクトリにあるパッケージをインクルードする場合:

@nox.session
def test_project(session):
    # pip install . の操作と同じ
    session.install(".")
    session.run("pytest")

コマンドの実行制御

セッション内の環境において外部コマンドを実行するにはsession.run()メソッドを使用します。

基本実行

session.install("black")
session.run("black", "src/")

引数の指定

コマンドラインフラグやパラメータは追加の引数として渡せます:

session.run(
    "pytest",
    "tests",
    "-x",
    "--verbose"
)

環境変数の設定

特定のコンテキストで実行する際、環境変数を定義可能:

session.run(
    "pytest",
    env={
        "API_KEY": "secret_value",
        "LOG_LEVEL": "debug"
    }
)

対象セッションの選択

複数の定義がある場合、デフォルトではすべてが実行されますが、特定のもののみ指定することも可能です。

# リスト表示
nox --list

特定のセッションを実行する場合:

nox --sessions lint

あるいは短縮形を使います:

nox -s tests

異なる Python バージョンでの検証

特定のライブラリやインターフェースが複数のインタープリタで動作するか確認するには、セッションのデコレータで対象のバージョンを指定します。

単一のバージョン

@nox.session(python="3.10")
def verify(session):
    pass

複数のバージョン(リスト型)

一度の呼び出しで複数のバリエーションを回すことができます:

@nox.session(python=["3.9", "3.10", "3.11"])
def run_suite(session):
    pass

リスト型の指定をした際、それぞれが個別のサブセッションとして展開されます(例:run_suite-3.9)。

Conda 環境との連携

データサイエンス分野などで Anaconda 環境を維持したい場合、バックエンド設定を変更します:

@nox.session(venv_backend="conda")
def analyze(session):
    pass

内部では conda_install メソッドを利用してパッケージを解決します:

session.conda_install("matplotlib")

Pip を経由して入れる必要がある場合は、依存関係の競合を防ぐために --no-deps オプションの使用が強く推奨されます:

session.install("some-package", "--no-deps")

パラメータ化の活用

同じロジックを多様な引数で実行したい場合、parametrize アノテーションを活用します。これはテストフレームワークの概念に近い機能です。

@nox.session
@nox.parametrize("version", ["4.0", "4.2"])
def test_with_version(session, version):
    session.install(f"myapp=={version}")
    session.run("pytest")

これをリスト表示すると、各バージョンごとの別々のタスクとして列挙されます。これにより重複するコード記述を避けることができます。

タグ: nox python-automation task-management continuous-integration virtualenv

10月23日 02:26 投稿