メインコンテンツへスキップ

PythonでタスクランナーTaskfileを使う

·2616 文字·6 分
目次

はじめに
#

タスクランナーTaskfileをPython環境にインストールし、Ruff, mypy, pytestを実行する方法をまとめました。 タスクランナーとは、ソフトウェアの開発における作業を自動化するツールです。 また、Taskfileの正式名称はTaskですが、一般的な名称のため、この記事ではTaskfileと記載します。

検証環境は以下の通りです。

  • Windows 10 Home 22H2

  • Python 3.13.5

  • Taskfile 3.44.1

  • Ruff 0.12.8

  • mypy 1.17.1

  • pytest 8.4.1

Python向けタスクランナー比較
#

Taskfile以外にもPythonで使用できるタスクランナーがあるため、各ツールを比較しました(2025/8/12現在)。

ツール 最終リリース日 GitHubスター数
Taskfile 2025/7/24 13000
invoke 2023/7/13 4597
poethepoet 2025/8/12 1800
taskipy 2024/11/27 620

最終リリース日はPyPiの「リリース日」としています。

TaskfileのGitHubスター数が最も多く、開発が活発なため採用しました。

Taskfileの概要
#

TaskfileはGo言語で実装されたタスクランナーです。 公式サイトのInstallationのページにあるように、Linuxのsnap, Node.jsのnpm, WindowsのWinGetなど様々な環境にインストール可能です。 また、Taskfileはシングルバイナリで実行されます。

Taskfileの基本的な使い方
#

インストール
#

以下のコマンドを実行し、TaskfileをPython環境にインストールします(必要に応じて、uvやvenvで仮想環境を作成して下さい)。

pip install go-task-bin

インストールの完了後、以下のコマンドでTaskfileのバージョンが表示されることを確認します。

> task --version
3.44.1+pypi

また、task --helpコマンドでヘルプを表示できます。

設定ファイル
#

以下のコマンドを実行し、Taskfileの設定ファイルTaskfile.ymlを作成します。

task --init

Taskfile.ymlの中身は以下のようになっています。

# https://taskfile.dev

version: '3'

vars:
  GREETING: Hello, World!

tasks:
  default:
    cmds:
      - echo "{{.GREETING}}"
    silent: true

主な設定を解説します。

  • version: Taskfileのバージョンを指定
  • vars: 変数を設定
  • tasks: 実行するタスクを定義
    • default: タスク名
      • cmds: 実行するコマンドを定義
      • silent: trueのとき、Taskfileのメタ情報を表示しない

タスクの実行
#

Taskfile.ymlと同じ階層のディレクトリでtaskコマンドを実行すると、タスクが実行されます。

> task
Hello, World!

上述のTaskfile.ymlでは、echo "Hello, World!"というコマンドが実行されます。 したがって、コンソールにはHello, World!と表示されます。

タスクの終了ステータスと続行
#

この節では、タスクの終了ステータスに対するTaskfileの挙動について記載します。 タスクのコマンドをcmdsに続けて記述するとき、各コマンドの終了ステータスが0のときのみ実行が継続されます。

Taskfile.ymltasksを以下のように変更します。

tasks:
  default:
    cmds:
      - exit 0
      - echo "{{.GREETING}}"
    silent: false

Taskfileの実行結果は以下になり、echoまで実行されていることが分かります。

> task
task: [default] exit 0
task: [default] echo "Hello, World!"
Hello, World!

次に、exitの終了ステータスを1に変更します。

tasks:
  default:
    cmds:
      - exit 1
      - echo "{{.GREETING}}"
    silent: false

Taskfileの実行結果は以下になりました。exit 1でfailし、echoは実行されません。

> task
task: [default] exit 1
task: Failed to run task "default": exit status 1

この挙動を利用して、複数の開発ツールの実行を制御することができます。 例えば「Ruffによる構文チェックに失敗する場合、Pytestによる自動テストを実行しない」などです。

開発ツールの終了ステータス
#

Ruff, mypy, pytestは、チェック対象のコードが正常な場合、いずれも終了ステータスは0になります。 詳細は以下になります。

Ruff
#

Ruffのlinter機能では、違反がない場合、もしくは違反が全て自動的に修正された場合のみ、終了ステータスが0になります。 また、Ruffのformatter機能では、以下の場合に終了ステータスが0になります。

  • ruff formatで全ファイルを正常に整形できた場合

  • ruff format --checkで全ファイルが整形の必要がない場合

  • The Ruff Linter

  • The Ruff Formatter

mypy
#

mypyの終了ステータスは公式にドキュメント化されていないようですが、issueによるとおおむね以下になるようです。

  • 0: 型エラーがない場合
  • 1: 何らかの型エラーがある場合
  • 2: クラッシュした場合や、引数が誤っている場合など

Document exit codes for mypy and dmypy - Issue #6003 - GitHub

pytest
#

pytestの終了ステータスは、全てのテストに成功した場合のみ0になります。 それ以外の場合、終了ステータスは1~5になります。

Exit codes - pytest documentation

Taskfileの編集
#

いよいよRuff, mypy, pytestの一連の処理をTaskfile.ymlに設定します。 処理の順序は以下とします。

  1. Ruffによるlint
  2. Ruffによる整形チェック
  3. mypyによる型チェック
  4. pytestによる自動テスト

順序は好みがあると思いますが、処理時間が短いものを先にした方がよいと思います(短時間でエラーが出た方が修正のサイクルを早く回せるため)。

また、プロジェクトのフォルダ構成は以下とします。

src/   # ソフトウェア本体のスクリプト
tests/   # テスト用スクリプト
Taskfile.yml
pyproject.toml

Taskfile.ymlにコマンドを設定します。 実行対象のフォルダを変数SRC_DIR, TEST_DIRで定義しています。 また、Ruffにはコードの自動修正機能がありますが、その機能を使用せず、単にエラーを出力するのみに留めています。

version: '3'

vars:
  SRC_DIR: "."
  TEST_DIR: "./tests"

tasks:
  default:
    cmds:
      - ruff check {{.SRC_DIR}}
      - ruff format --check {{.SRC_DIR}}
      - mypy {{.SRC_DIR}}
      - pytest {{.TEST_DIR}}
    silent: false

pyproject.tomlの中身は以下のようにして、pytest実行時のパスにsrcフォルダを追加します。

[tool.pytest.ini_options]
pythonpath = "src"

ここまででファイルの編集は完了です。

最後にTaskfileで4つのコマンドをまとめて実行します。 プロジェクトの一番上の階層でtaskコマンドを実行するだけです。 全てのチェックに成功する(終了ステータスが0になる)場合、以下のように表示されます。

> task
task: [default] ruff check .
All checks passed!
task: [default] ruff format --check .
2 files already formatted
task: [default] mypy .
Success: no issues found in 2 source files
task: [default] pytest ./tests
=================================== test session starts ===================================
platform win32 -- Python 3.13.5, pytest-8.4.1, pluggy-1.6.0
rootdir: E:\document\Python Scripts\task_test
configfile: pyproject.toml
collected 1 item

tests\test_foo.py .                                                                  [100%]

==================================== 1 passed in 0.02s ====================================

一方、最初のruff checkコマンドで失敗する場合、以下のようになります。 ruff format --check以降のコマンドは実行されません。

> task
task: [default] ruff check .
src\foo.py:6:5: F841 Local variable `y` is assigned to but never used
  |
4 | def myfunc(x: int) -> int:
5 |     """func."""
6 |     y = 300
  |     ^ F841
7 |     return 2 * x
  |
  = help: Remove assignment to unused variable `y`

Found 1 error.
No fixes available (1 hidden fix can be enabled with the `--unsafe-fixes` option).
task: Failed to run task "default": exit status 1

参考
#

Helve
著者
Helve
関西在住、電機メーカ勤務のエンジニア。X(旧Twitter)で新着記事を配信中です

関連記事

Pythonの列挙型Enumを検証
·1462 文字·3 分
Pythonの列挙型Enumについて、同値判定の方法、型ヒントやdocstringの書き方などを調査した結果を備忘録として残します。
SphinxでPython docstringからドキュメントを自動生成する
·2014 文字·5 分
ドキュメント生成ツールSphinxを使って、Pythonスクリプトのクラスや関数のdocstringからHTMLドキュメントを自動生成する方法を解説する。
【Python】dataclassの継承と初期値・型ヒント・メソッドのオーバーライド
·2442 文字·5 分
Pythonのdataclassを継承して派生クラスを作る方法、および初期値・型ヒント・メソッドのオーバーライドについて解説します。
pyproject.tomlからpip installコマンドでPythonのライブラリをインストールする
·1918 文字·4 分
Pythonのパッケージ設定ファイルpyproject.tomlに記載されたPythonのパッケージを、パッケージ管理システムpipでインストールする方法を解説します。
Scikit-learnのDecisionTreeClassifierクラスによる分類木
·3865 文字·8 分
分類木 (classification tree) は、分析したデータが属するカテゴリー(クラス)を予測する分類アルゴリズムの1つです。分類木では、Yes/Noによる分岐を何度か繰り返して、分類の予測を返します。
Cloudflare Pages上でSphinxサイトを自動デプロイする
·2235 文字·5 分
静的サイトホスティングサービスのCloudflare Pages上でドキュメント生成ツールSphinxを自動デプロイする手順を備忘録としてまとめました。