【Python】Pixiの特異性「Task」の基本
タスクの全容を知る
パッケージマネージャーは数多あれ、それがタスクを持つことは尠少、しかしその利便たるや計り知れないところがある。本記事は
なお、一部の操作はコマンドpixi task ~で行うことができるが、本記事ではこれを扱わない。
0. ワークスペース新規作成
まずは新規にワークスペースを一つ作る。
pixi init tasks
tasksフォルダーと、その中にpixi.tomlが作られただろう。本記事では、このpixi.tomlを編集することでタスクを扱っていく。
[workspace]
channels = ["conda-forge"]
name = "tasks"
platforms = ["win-64"] # OSによる
version = "0.1.0"
[tasks]
[dependencies]
一応、ワークスペースに
pixi add python
pixi.tomlが更新され、
[dependencies]
python = ">=3.13.7,<3.14"
最終的なpixi.toml
長いのでアコーディオン
[workspace]
channels = ["conda-forge"]
name = "tasks"
platforms = ["win-64"]
version = "0.1.0"
[dependencies]
python = ">=3.13.7,<3.14"
[activation.env]
WORLD_ENVIRONMENT = "world"
[tasks]
make_dir = "mkdir -p src"
create_source_file = "echo 'import sys\n\nprint(sys.version)' > src/main.py"
run_script = "python src/main.py"
running_all_flow = [
{ task = "make_dir" },
{ task = "create_source_file" },
{ task = "run_script" }
]
mkdir_src = { cmd = "mkdir -p src" }
create_main_py = { cmd = "echo 'import sys\n\nprint(sys.version)' > src/main.py", depends-on = ["mkdir_src"] }
run_main_py = { cmd = "python src/main.py", depends-on = ["create_main_py"] }
delete_source_dir = "rm -rf src"
unique_task = "python --version"
show_all_unique_tasks = { depends-on = [
{ task = "unique_task", environment = "default"},
{ task = "unique_task", environment = "node-env"}
] }
print_hello = "python -c 'print(\"Hello from Python\")'"
hello_from_all_envs = { depends-on = [
{ task = "print_hello", environment = "default"},
{ task = "log_hello", environment = "node-env"}
] }
run_in_src_dir = { cmd = "python main.py", cwd = "src" }
greet_with_name = { cmd = "python -c 'print(\"Hello, {{ name }}\")'", args = ["name"] }
greet_with_optional = { cmd = "python -c 'print(\"Hello, {{ name }}\")'", args = [{ "arg" = "name", "default" = "World" }] }
addition = { cmd = "python -c 'print({{ a }} + {{ b }})'", args = [
{ "arg" = "a", "default" = "0" },
{ "arg" = "b", "default" = "0" }
] }
make_user_dir = { cmd = "mkdir -p users/{{ username }}", args = ["username"] }
create_user_file = { cmd = """echo 'print("Hello, {{ username }}")' > users/{{ username }}/{{ username }}.py""", depends-on = [
{task = "make_user_dir", args = ["{{ username }}"]}
], args = ["username"] }
minus_addition = { depends-on = [
{ task = "addition", args = [
{ "a" = "-6" },
{ "b" = "-3" }
] }
] }
upper_case = { cmd = "echo {{ text | upper }}", args = ["text"] }
lower_case = { cmd = "echo {{ text | lower }}", args = ["text"] }
division = { cmd = """python -c '''
{% if not b == "0" %}
print({{ a }} / {{ b }})
{% else %}
print("Error: Division by zero")
{% endif %}
'''
""", args = [
{ "arg" = "a", "default" = "1" },
{ "arg" = "b", "default" = "1" }
] }
concatenate = { cmd = "echo {{ a + b }}", args = ["a", { arg = "b", default = "!" }] }
for_split = { cmd = "{% for name in names | split %} echo {{ name }};{% endfor %}", args = ["names"] }
_hidden = "echo hidden"
create_main_py_cache = { cmd = "echo 'import sys\n\nprint(sys.version)' > src/main.py", depends-on = ["mkdir_src"], outputs = ["src/main.py"] }
run_main_py_cache = { cmd = "python src/main.py", depends-on = ["create_main_py_cache"], inputs = ["src/main.py"] }
hello_world_env_var = { cmd = "echo $HELLO_ENVIRONMENT $WORLD_ENVIRONMENT", env = { HELLO_ENVIRONMENT = "hello" } }
ls = "ls"
[environments]
node-env = { features = ["f_node"], no-default-feature = true }
[feature.f_node]
dependencies = { nodejs = ">=24.9.0,<24.10" }
tasks = { unique_task = "npm --version", log_hello = "node -e 'console.log(\"Hello from Node.js\")'" }
1. コマンド入力の簡略化
手始めに、四つのタスクを登録する。
[tasks]
# srcフォルダーが無ければ作る
make_dir = "mkdir -p src"
# srcフォルダーの中にmain.pyを作る
create_source_file = "echo 'import sys\n\nprint(sys.version)' > src/main.py"
# main.pyを実行する
run_script = "python src/main.py"
# srcフォルダーを内容ごと消す
delete_source_dir = "rm -rf src"
これらのタスクを実行する時は、pixi run タスク名と入力する。
各タスク実行の様子
# 実行前の様子確認
PS C:\⋯\tasks> ls -Name
.pixi
.gitattributes
.gitignore
pixi.lock
pixi.toml
# タスク実行
PS C:\⋯\tasks> pixi run make_dir
Pixi task (make_dir): mkdir -p src
# 実行後の様子確認
PS C:\⋯\tasks> ls -Name
.pixi
src # ☚ srcフォルダーが作られた
.gitattributes
.gitignore
pixi.lock
pixi.toml
# 実行前の様子確認(何もないため何も表示されない)
PS C:\⋯\tasks> ls .\src\ -Name
# タスク実行
PS C:\⋯\tasks> pixi run create_source_file
Pixi task (create_source_file): echo 'import sys
print(sys.version)' > src/main.py
# 実行後の様子確認
PS C:\⋯\tasks> ls .\src\ -Name
main.py
# ファイルの内容確認
PS C:\⋯\tasks> type .\src\main.py
import sys
print(sys.version)
# タスク実行
PS C:\⋯\tasks> pixi run run_script
Pixi task (run_script): python src/main.py
3.13.7 | packaged by conda-forge | (main, Sep 3 2025, 14:18:04) [MSC v.1944 64 bit (AMD64)]
# 実行前の様子確認
PS C:\⋯\tasks> ls -Name
.pixi
src
.gitattributes
.gitignore
pixi.lock
pixi.toml
# タスク実行
PS C:\⋯\tasks> pixi run delete_source_dir
Pixi task (delete_source_dir): rm -rf src
# 実行後の様子確認
PS C:\⋯\tasks> ls -Name
.pixi
.gitattributes
.gitignore
pixi.lock
pixi.toml
問題点:実行順序によるエラー
当然ながら、main.pyが存在しない状態でrun_scriptタスクを実行すれば、エラーになる。
PS C:\⋯\tasks> pixi run run_script
Pixi task (run_script): python src/main.py
C:\⋯\tasks\.pixi\envs\default\python.exe: can't open file 'C:\\⋯\\tasks\\src\\main.py': [Errno 2] No such file or directory
run_scriptタスクが正しく実行されるには、create_source_fileタスクによってmain.pyが作られていなければならない。
更に、create_source_fileタスクが正しく実行されるには、make_dirタスクによってsrcフォルダーが作られていなければならない。
PS C:\⋯\tasks> pixi run create_source_file
Pixi task (create_source_file): echo 'import sys
print(sys.version)' > src/main.py
error opening file for redirect (C:\⋯\tasks\src/main.py). 指定されたパスが見つかりません。 (os error 3)
このような状況を、「タスク同士に依存関係がある」と言う。
2. 依存関係
タスク同士に依存関係がある場合、その通り正しい順序で実行しなければならない。これを強制するためには、depends-onで依存関係を定めておく。
depends-on:依存関係定義の基本
ここで、pixi.tomlにタスクを追加する。演じることは先のものと全く同じだが、depends-onによる依存関係の定義を付した。
[tasks]
mkdir_src = { cmd = "mkdir -p src" }
create_main_py = { cmd = "echo 'import sys\n\nprint(sys.version)' > src/main.py", depends-on = ["mkdir_src"] }
run_main_py = { cmd = "python src/main.py", depends-on = ["create_main_py"] }
このように依存関係を定めたことで、run_main_pyタスクを実行すると、依存関係を遡って全てのタスクが実行される。
# srcフォルダーが無い状態
PS C:\⋯\tasks> ls -Name
.pixi
.gitattributes
.gitignore
pixi.lock
pixi.toml
# run_main_pyの実行命令
PS C:\⋯\tasks> pixi run run_main_py
# mkdir_srcの実行
Pixi task (mkdir_src): mkdir -p src
# create_main_pyの実行
Pixi task (create_main_py): echo 'import sys
print(sys.version)' > src/main.py
# run_main_pyの実行
Pixi task (run_main_py): python src/main.py
3.13.7 | packaged by conda-forge | (main, Sep 3 2025, 14:18:04) [MSC v.1944 64 bit (AMD64)]
# 実行後はsrcフォルダーが作られている
PS C:\⋯\tasks> ls -Name
.pixi
src
.gitattributes
.gitignore
pixi.lock
pixi.toml
alias:依存関係の後付け
depends-onを使わずとも、依存関係を定めることができる。先の、依存関係を定めていないタスクについて、次の若く後から依存関係を定める。
[tasks]
make_dir = "mkdir -p src"
create_source_file = "echo 'import sys\n\nprint(sys.version)' > src/main.py"
run_script = "python src/main.py"
# 依存関係を定める配列
running_all_flow = [
{ task = "make_dir" },
{ task = "create_source_file" },
{ task = "run_script" }
]
running_all_flowそれ自体はタスクというよりも、別名(alias)である。しかし実行時はタスク同様にして扱うことができる。
PS C:\⋯\tasks> pixi run running_all_flow
Pixi task (make_dir): mkdir -p src
Pixi task (create_source_file): echo 'import sys
print(sys.version)' > src/main.py
Pixi task (run_script): python src/main.py
3.13.7 | packaged by conda-forge | (main, Sep 3 2025, 14:18:04) [MSC v.1944 64 bit (AMD64)]
難:環境と依存タスク
pixi.tomlにて、新たに一つ
[environments]
# Node.jsの環境
# `no-default-feature = true`は`unique_task`という名前の重複を許すために付している
node-env = { features = ["f_node"], no-default-feature = true }
[feature.f_node]
# pixi add -f f_node nodejs
dependencies = { nodejs = ">=24.9.0,<24.10" }
tasks = { unique_task = "npm --version" }
次に、新たな二つのタスクを追加する。
[tasks]
unique_task = "python --version"
show_all_unique_tasks = { depends-on = [
{ task = "unique_task", environment = "default"},
{ task = "unique_task", environment = "node-env"}
] }
この内、depends-onのみからなるタスクは
現状、各環境について次のようになっている。
| 環境 | パッケージ | タスクunique_taskの定義 |
|---|---|---|
default |
python |
unique_task = "python --version" |
node-env |
nodejs |
unique_task = "npm --version" |
PS C:\⋯\tasks> pixi run show_all_unique_tasks
Pixi task (unique_task in default): python --version
Python 3.13.7
Pixi task (unique_task in node-env): npm --version
11.6.0
今unique_taskという同名のタスクを用いたが、必ずしも同名である必要はない。print_helloとlog_helloという二つの全く異なるタスクを使っても、依存タスクは同様に働く。
[tasks]
print_hello = "python -c 'print(\"Hello from Python\")'"
hello_from_all_envs = { depends-on = [
{ task = "print_hello", environment = "default"},
{ task = "log_hello", environment = "node-env"}
] }
[environments]
node-env = { features = ["f_node"], no-default-feature = true }
[feature.f_node]
dependencies = { nodejs = ">=24.9.0,<24.10" }
tasks = { unique_task = "npm --version", log_hello = "node -e 'console.log(\"Hello from Node.js\")'" }
PS C:\⋯\tasks> pixi run hello_from_all_envs
Pixi task (print_hello in default): python -c 'print("Hello from Python")'
Hello from Python
Pixi task (log_hello in node-env): node -e 'console.log("Hello from Node.js")'
Hello from Node.js
3. Current Working Directory
pixi.tomlのある位置となる。
先述したrun_main_pyの定義を改めて見てみよう。
run_main_py = { cmd = "python src/main.py", depends-on = ["create_main_py"] }
main.pyはsrcフォルダーにあるため、src/main.pyとしている。
では試みに、現在の位置をsrcにしてみよう。なお、依存関係は省略している。
run_in_src_dir = { cmd = "python main.py", cwd = "src" }
PS C:\⋯\tasks> pixi run run_in_src_dir
Pixi task (run_in_src_dir in default): python main.py
3.13.7 | packaged by conda-forge | (main, Sep 3 2025, 14:18:04) [MSC v.1944 64 bit (AMD64)]
srcフォルダーになるため、単にmain.pyとできる。
4. タスク引数
必須のタスク引数
単純な例から始めよう。タスク引数に与えた文字列を使って挨拶する、単純なものである。
[tasks]
greet_with_name = { cmd = "python -c 'print(\"Hello, {{ name }}\")'", args = ["name"] }
タスク引数に与えられた値にはnameという名がつく。タスク引数nameをコマンド上に展開するには、{{name}}とする。
PS C:\⋯\tasks> pixi run greet_with_name takahashi
Pixi task (greet_with_name in default): python -c 'print("Hello, takahashi")'
Hello, takahashi
# 必須のため、タスク引数を与えないとエラーになる
PS C:\⋯\tasks> pixi run greet_with_name
Error: × no value provided for argument 'name' for task 'greet_with_name'
タスク引数の初期値
初期値を定めることで、タスク引数を任意入力とすることができる。
[tasks]
greet_with_optional = { cmd = "python -c 'print(\"Hello, {{ name }}\")'", args = [{ "arg" = "name", "default" = "World" }] }
# 省略した場合
PS C:\⋯\tasks> pixi run greet_with_optional
Pixi task (greet_with_optional in default): python -c 'print("Hello, World")'
Hello, World
# 省略しない場合
PS C:\⋯\tasks> pixi run greet_with_optional takachiho
Pixi task (greet_with_optional in default): python -c 'print("Hello, takachiho")'
Hello, takachiho
複数のタスク引数
タスク引数は複数定めることができる。
[tasks]
addition = { cmd = "python -c 'print({{ a }} + {{ b }})'", args = [
{ "arg" = "a", "default" = "0" },
{ "arg" = "b", "default" = "0" }
] }
PS C:\⋯\tasks> pixi run addition
Pixi task (addition in default): python -c 'print(0 + 0)'
0
PS C:\⋯\tasks> pixi run addition 1 2
Pixi task (addition in default): python -c 'print(1 + 2)'
3
依存と引数
依存先のタスクに対してもまた、タスク引数を与えることができる。
# ユーザー名を基にフォルダーを作る
make_user_dir = { cmd = "mkdir -p users/{{ username }}", args = ["username"] }
# ユーザー名.py を作る
create_user_file = { cmd = """echo 'print("Hello, {{ username }}")' > users/{{ username }}/{{ username }}.py""", depends-on = [
{task = "make_user_dir", args = ["{{ username }}"]}
], args = ["username"] }
# タスク実行
PS C:\⋯\tasks> pixi run create_user_file tabayama
Pixi task (make_user_dir in default): mkdir -p users/tabayama
Pixi task (create_user_file in default): echo 'print("Hello, tabayama")' > users/tabayama/tabayama.py
# tabayamaのフォルダーとファイルが作られている
PS C:\⋯\tasks> tree .\users\ /f
Folder PATH listing for volume OS
Volume serial number is ⋯
C:\⋯\TASKS\USERS
└───tabayama
tabayama.py
PS C:\⋯\tasks> type .\users\tabayama\tabayama.py
print("Hello, tabayama ")
また、引数名を明示することもできる。
[tasks]
addition = { cmd = "python -c 'print({{ a }} + {{ b }})'", args = [
{ "arg" = "a", "default" = "0" },
{ "arg" = "b", "default" = "0" }
] }
# 負の値を渡す
minus_addition = { depends-on = [
{ task = "addition", args = [
{ "a" = "-6" },
{ "b" = "-3" }
] }
] }
PS C:\⋯\tasks> pixi run minus_addition
Pixi task (addition in default): python -c 'print(-6 + -3)'
-9
MiniJinja

コマンド上にタスク引数の値を展開する際、{{ 引数名 }}という表記を用いてきた。これは
従って{{ ~ }}という表記自体は、屢〻
詳しくは
条件分岐
除算を例に取ると、
[tasks]
division = { cmd = """python -c '''
{% if not b == "0" %}
print({{ a }} / {{ b }})
{% else %}
print("Error: Division by zero")
{% endif %}
'''
""", args = [
{ "arg" = "a", "default" = "1" },
{ "arg" = "b", "default" = "1" }
] }
PS C:\⋯\tasks> pixi run division 10 3
Pixi task (division in default): python -c '''
print(10 / 3)
'''
3.3333333333333335
PS C:\⋯\tasks> pixi run division 10 0
Pixi task (division in default): python -c '''
print("Error: Division by zero")
'''
Error: Division by zero
反復
[tasks]
for_split = { cmd = "{% for name in names | split %} echo {{ name }};{% endfor %}", args = ["names"] }
PS C:\⋯\tasks> pixi run for_split_list 'nagashima ezaki ogata'
Pixi task (for_split_list in default): echo nagashima; echo ezaki; echo ogata;
nagashima
ezaki
ogata
5. 命名と秘匿
タスクの命名について次の規則がある。
- タスクの名前を
_から始めると、pixi task listなどに表示されなくなる。 - 半角スペース
を含めることができない。 - 一意で重複しない。
特に、_から始まる命名によって、タスクを秘匿することができる。
タスク一覧の表示
タスクの一覧はpixi task listで表示できるが、pixi runの表示の方が読み好い。
PS C:\⋯\tasks> pixi task list -s
Tasks per environment:
----------------------
default: addition, concatenate, create_main_py, create_main_py_cache, create_source_file, create_user_file, delete_source_dir, division, for_split, greet_with_name, greet_with_optional, hello_from_all_envs, hello_world_env_var, lower_case, ls, make_dir, make_user_dir, minus_addition, mkdir_src, print_hello, run_in_src_dir, run_main_py, run_main_py_cache, run_script, running_all_flow, show_all_unique_tasks, unique_task, upper_case
node-env: log_hello, unique_task
PS C:\⋯\tasks> pixi run
Available tasks:
addition
concatenate
create_main_py
create_main_py_cache
create_source_file
create_user_file
delete_source_dir
division
for_split
greet_with_name
greet_with_optional
hello_from_all_envs
hello_world_env_var
log_hello
lower_case
ls
make_dir
make_user_dir
minus_addition
mkdir_src
print_hello
run_in_src_dir
run_main_py
run_main_py_cache
run_script
running_all_flow
show_all_unique_tasks
unique_task
upper_case
_から始まる名前が一つも現れていないことが分かる。
タスク一覧のJSON 表示
タスクの一覧は_から始まるタスクも秘匿されず、名を連ねている。
PS C:\⋯\tasks> pixi task list --json | Out-String -Stream | sls -Pattern "hidden" -Context 0
"name": "_hidden",
"cmd": "echo hidden",
6. キャッシュ
ここで、先述のタスクを振り返る。
[tasks]
mkdir_src = { cmd = "mkdir -p src" }
create_main_py = { cmd = "echo 'import sys\n\nprint(sys.version)' > src/main.py", depends-on = ["mkdir_src"] }
run_main_py = { cmd = "python src/main.py", depends-on = ["create_main_py"] }
これらは依存関係を定義し、実行順序によるエラーが起こらないようになったものであった。しかし、main.pyが存在する場合でも必ず上書きしている。この問題はキャッシュを使うことで解消することができる。
キャッシュは入力と出力との二種あり、且つその対象はファイルであるらしい。つまり、フォルダーは対象とならない。
[tasks]
# 出力:src/main.py が存在する場合、再実行されない
create_main_py_cache = { cmd = "echo 'import sys\n\nprint(sys.version)' > src/main.py", depends-on = ["mkdir_src"], outputs = ["src/main.py"] }
# 入力:src/main.py が変更されていない場合、再実行されない
run_main_py_cache = { cmd = "python src/main.py", depends-on = ["create_main_py_cache"], inputs = ["src/main.py"] }
# 一度目は実行される
PS C:\⋯\tasks> pixi run run_main_py_cache
Pixi task (mkdir_src in default): mkdir -p src
Pixi task (create_main_py_cache in default): echo 'import sys
print(sys.version)' > src/main.py
Pixi task (run_main_py_cache in default): python src/main.py
3.13.7 | packaged by conda-forge | (main, Sep 3 2025, 14:18:04) [MSC v.1944 64 bit (AMD64)]
# 二度目は実行されない
PS C:\⋯\tasks> pixi run run_main_py_cache
Pixi task (mkdir_src in default): mkdir -p src
Pixi task (create_main_py_cache in default): echo 'import sys
print(sys.version)' > src/main.py
Task 'create_main_py_cache' can be skipped (cache hit) 🚀
Pixi task (run_main_py_cache in default): python src/main.py
Task 'run_main_py_cache' can be skipped (cache hit) 🚀
outputs:存在の確認
outputsには、タスクによって生成されるファイルを指定する。このファイルが存在しているならば、それ以上タスクを実行する必要はない。
inputs:変更の確認
inputsには、タスクが使用するファイルを指定する。実行するファイルや、参照する設定ファイルなどが該当する。このファイルに変更がないならば、それ以上タスクを実行する必要はない。
7. 環境変数
タスク内で環境変数を設定・使用することができる。なおターミナルでこれらを使えるわけではない。
[activation.env]
WORLD_ENVIRONMENT = "world"
[tasks]
hello_world_env_var = { cmd = "echo $HELLO_ENVIRONMENT $WORLD_ENVIRONMENT", env = { HELLO_ENVIRONMENT = "hello" } }
PS C:\⋯\tasks> pixi run hello_world_env_var
Pixi task (hello_world_env_var in default): echo $HELLO_ENVIRONMENT $WORLD_ENVIRONMENT
hello world
環境変数の定義には幾つか手段がある。同名の環境変数を異なる手段で定義した場合、既定の優先順位によって一方が採用される。
必要最小限の環境変数
プログラムで使用できる環境変数は、必ずしもプログラムに関係あるものではない。不要なものを除外し、プログラムに必要最小限の環境変数を備えた環境を使ってタスクを実行することができる。なお、一部の環境変数(USERやHOMEなど)は除外されない。
確認用ワークスペースでの実験
# pixiのインストール
/content# curl -fsSL https://pixi.sh/install.sh | sh
This script will automatically download and install Pixi (latest) for you.
Getting it from this url: https://github.com/prefix-dev/pixi/releases/latest/download/pixi-x86_64-unknown-linux-musl.tar.gz
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
0 0 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0
0 0 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0
100 24.2M 100 24.2M 0 0 26.6M 0 --:--:-- --:--:-- --:--:-- 26.6M
The 'pixi' binary is installed into '/root/.pixi/bin'
Updating '/root/.bashrc'
Please restart or source your shell.
# ターミナルの再起動
/content# source /root/.bashrc
# ワークスペース`clean`作成
/content# pixi init clean
✔ Created /content/clean/pixi.toml
# 移動
/content# cd clean/
[workspace]
channels = ["conda-forge"]
name = "clean"
platforms = ["linux-64"]
version = "0.1.0"
[tasks]
path = { cmd = "echo $PATH" }
home = { cmd = "echo $HOME" }
cuda_ver = { cmd = "echo $CUDA_VERSION" }
path_clean = { cmd = "echo $PATH", clean-env = true }
home_clean = { cmd = "echo $HOME", clean-env = true }
cuda_ver_clean = { cmd = "echo $CUDA_VERSION", clean-env = true }
[dependencies]
# cleanでない環境
/content/clean# pixi run path
✨ Pixi task (path): echo $PATH
/content/clean/.pixi/envs/default/bin:/root/.pixi/bin:/opt/bin:/usr/local/nvidia/bin:/usr/local/cuda/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/tools/node/bin:/tools/google-cloud-sdk/bin
/content/clean# pixi run home
✨ Pixi task (home): echo $HOME
/root
/content/clean# pixi run cuda_ver
✨ Pixi task (cuda_ver): echo $CUDA_VERSION
12.5.1
# cleanな環境
/content/clean# pixi run path_clean
✨ Pixi task (path_clean): echo $PATH
/content/clean/.pixi/envs/default/bin
/content/clean# pixi run home_clean
✨ Pixi task (home_clean): echo $HOME
/root
/content/clean# pixi run cuda_ver_clean
✨ Pixi task (cuda_ver_clean): echo $CUDA_VERSION
補遺1. :deno_task_shell
deno_task_shellが使われている。
これまでにもタスク内でmkdirやrm、echoといったコマンドを用いてきたが、これはあくまでもdeno_task_shellによって提供されているコマンドである。つまりdeno_task_shellのものであり、
その分かりやすい証左に、lsコマンドが使えない。
[tasks]
ls = "ls"
PS C:\⋯\tasks> pixi run ls
Pixi task (ls in default): ls
ls: command not found
Windowsとls
コマンドプロンプトではlsが使えず、dirがそれに対応することが知られている。
C:\>ls
'ls' は、内部コマンドまたは外部コマンド、
操作可能なプログラムまたはバッチ ファイルとして認識されていません。
しかしGet-ChildItemの別名としてlsが存在する。このため、lsを使うことはできるのである。
コマンド一覧
cpmvrmmkdirpwdsleepechocatexitheadunsetxargs
参考:Windowsで実行した様子
[workspace]
channels = ["conda-forge"]
name = "deno_sample"
platforms = ["win-64"]
version = "0.1.0"
[tasks.echo]
cmd = "echo {{ message }}"
args = [
{ "arg" = "message", "default" = "Hello, World!" }
]
[tasks.create_text]
cmd = "echo {{ content }} > {{ filename }}.txt"
args = [
{ "arg" = "content", "default" = "Hello, World!" },
{ "arg" = "filename", "default" = "output" }
]
[tasks.copy_file]
cmd = "cp {{ source }} {{ destination }}"
args = [
{ "arg" = "source" },
{ "arg" = "destination" }
]
[tasks.move_file]
cmd = "mv {{ source }} {{ destination }}"
args = [
{ "arg" = "source" },
{ "arg" = "destination" }
]
[tasks.remove_file]
cmd = "rm {{ filename }}"
args = [
{ "arg" = "filename" }
]
[tasks.make_directory]
cmd = "mkdir -p {{ directoryname }}"
args = [
{ "arg" = "directoryname" }
]
[tasks.print_working_directory]
cmd = "pwd"
[tasks.sleep]
cmd = "sleep {{ seconds }}"
args = [
{ "arg" = "seconds", "default" = "1" }
]
[tasks.concat_files]
cmd = "cat {{ filename }}"
args = [
{ "arg" = "filename" }
]
[tasks.exit]
cmd = "exit {{ code }}"
args = [
{ "arg" = "code", "default" = "0" }
]
[tasks.head]
cmd = "head -n {{ lines }} {{ filename }}"
args = [
{ "arg" = "filename" },
{ "arg" = "lines", "default" = "10" }
]
[tasks.unset]
cmd = "{{ variable }}={{ value }} ; echo ${{ variable }} ; unset {{ variable }} ; echo ${{ variable }}"
args = [
{ "arg" = "variable" },
{ "arg" = "value" }
]
[tasks.xargs]
cmd = "echo {{ items }} | xargs -n1 echo"
args = [
{ "arg" = "items", "default" = "item1 item2 item3" }
]
# command not found
[tasks.dir]
cmd = "dir"
[dependencies]
始めに、dirが使えないことを確認する。
# タスクでなければ使える
PS C:\⋯> dir -name
.pixi
.gitattributes
.gitignore
pixi.lock
pixi.toml
# タスクでは「command not found」となる
PS C:\⋯> pixi run dir
Pixi task (dir): dir
dir: command not found
Available tasks:
concat_files
copy_file
create_text
dir
echo
exit
head
make_directory
move_file
print_working_directory
remove_file
sleep
unset
xargs
次に、deno_task_shellのコマンドが使えることを一つ一つ確認する。
PS C:\⋯> pixi run echo
Pixi task (echo): echo Hello, World!
Hello, World!
PS C:\⋯> pixi run echo メッセージ
Pixi task (echo): echo メッセージ
メッセージ
PS C:\⋯> pixi run create_text
Pixi task (create_text): echo Hello, World! > output.txt
PS C:\⋯> ls -Name
.pixi
.gitattributes
.gitignore
output.txt
pixi.lock
pixi.toml
PS C:\⋯> pixi run create_text "大凡學文、初要膽大、終要心小。由麤入細、由俗入雅󠄂、由繁入簡、由豪蕩入純粹。" 放膽文
Pixi task (create_text): echo 大凡學文、初要膽大、終要心小。由麤入細、由俗入雅󠄂、由繁 入簡、由豪蕩入純粹。 > 放膽文.txt
⠁
PS C:\⋯> ls -Name
.pixi
.gitattributes
.gitignore
output.txt
pixi.lock
pixi.toml
放膽文.txt
PS C:\⋯> pixi run copy_file output.txt copied.txt
Pixi task (copy_file): cp output.txt copied.txt
PS C:\⋯> ls -Name
.pixi
.gitattributes
.gitignore
copied.txt
output.txt
pixi.lock
pixi.toml
放膽文.txt
PS C:\⋯> pixi run move_file output.txt hello_world.txt
Pixi task (move_file): mv output.txt hello_world.txt
PS C:\⋯> ls -Name
.pixi
.gitattributes
.gitignore
copied.txt
hello_world.txt
pixi.lock
pixi.toml
放膽文.txt
PS C:\⋯> pixi run remove_file copied.txt
Pixi task (remove_file): rm copied.txt
PS C:\⋯> ls -Name
.pixi
.gitattributes
.gitignore
hello_world.txt
pixi.lock
pixi.toml
放膽文.txt
PS C:\⋯> pixi run make_directory new_dir
Pixi task (make_directory): mkdir -p new_dir
PS C:\⋯> ls -Name
.pixi
new_dir
.gitattributes
.gitignore
hello_world.txt
pixi.lock
pixi.toml
放膽文.txt
PS C:\⋯> pixi run print_working_directory
Pixi task (print_working_directory): pwd
C:\⋯
PS C:\⋯> pixi run sleep
Pixi task (sleep): sleep 1
PS C:\⋯> pixi run sleep 5
Pixi task (sleep): sleep 5
PS C:\⋯> pixi run concat_files hello_world.txt
Pixi task (concat_files): cat hello_world.txt
Hello, World!
PS C:\⋯> pixi run concat_files 放膽文.txt
Pixi task (concat_files): cat 放膽文.txt
大凡學文、初要膽大、終要心小。由麤入細、由俗入雅󠄂、由繁入簡、由豪蕩入純粹。
PS C:\⋯> pixi run exit
Pixi task (exit): exit 0
PS C:\⋯> pixi run exit 1
Pixi task (exit): exit 1
PS C:\⋯> pixi run head pixi.toml
Pixi task (head): head -n 10 pixi.toml
[workspace]
channels = ["conda-forge"]
name = "deno_sample"
platforms = ["win-64"]
version = "0.1.0"
[tasks.echo]
cmd = "echo {{ message }}"
args = [
{ "arg" = "message", "default" = "Hello, World!" }
PS C:\⋯> pixi run head pixi.toml 15
Pixi task (head): head -n 15 pixi.toml
[workspace]
channels = ["conda-forge"]
name = "deno_sample"
platforms = ["win-64"]
version = "0.1.0"
[tasks.echo]
cmd = "echo {{ message }}"
args = [
{ "arg" = "message", "default" = "Hello, World!" }
]
[tasks.create_text]
cmd = "echo {{ content }} > {{ filename }}.txt"
args = [
PS C:\⋯> pixi run unset SOME_VALUE pixi_deno
Pixi task (unset): SOME_VALUE=pixi_deno ; echo $SOME_VALUE ; unset SOME_VALUE ; echo $SOME_VALUE
pixi_deno
PS C:\⋯> pixi run concat_files dirnames.txt
Pixi task (concat_files): cat dirnames.txt
dir1
dir2
dir3
PS C:\⋯> pixi run xargs dirnames.txt echo
Pixi task (xargs): cat dirnames.txt | xargs echo
dir1 dir2 dir3
PS C:\⋯> pixi run xargs dirnames.txt mkdir
Pixi task (xargs): cat dirnames.txt | xargs mkdir
PS C:\⋯> ls -Name
.pixi
dir1
dir2
dir3
new_dir
.gitattributes
.gitignore
dirnames.txt
hello_world.txt
pixi.lock
pixi.toml
放膽文.txt
互換性の無いその他のコマンド
以上のコマンドは環境に依存していないため、deno_task_shellに含まれないコマンドが全く使えないわけではない。
コマンドpixi shell-hookから、
PS C:\⋯> pixi shell-hook
$OutputEncoding = [System.Console]::OutputEncoding = [System.Console]::InputEncoding = [System.Text.Encoding]::UTF8
${Env:Path} = "C:\⋯\.pixi\envs\default;C:\⋯\.pixi\envs\default\Library/mingw-w64/bin;C:\⋯\.pixi\envs\default\Library/usr/bin;C:\⋯\.pixi\envs\default\Library/bin;C:\⋯\.pixi\envs\default\Scripts;C:\⋯\.pixi\envs\default\bin;C:\Program Files\PowerShell\7;C:\Program Files\Common Files\Oracle\Java\javapath;⋯以下略⋯
${Env:CONDA_SHLVL} = "1"
${Env:CONDA_PREFIX} = "C:\⋯\.pixi\envs\default"
${Env:PIXI_PROJECT_NAME} = "deno_sample"
${Env:PIXI_PROJECT_MANIFEST} = "C:\⋯\pixi.toml"
${Env:PIXI_PROJECT_ROOT} = "C:\⋯"
${Env:PIXI_EXE} = "C:\Users\⋯\.pixi\bin\pixi.exe"
${Env:PIXI_PROJECT_VERSION} = "0.1.0"
${Env:PIXI_IN_SHELL} = "1"
${Env:CONDA_DEFAULT_ENV} = "deno_sample"
${Env:PIXI_ENVIRONMENT_NAME} = "default"
${Env:PIXI_ENVIRONMENT_PLATFORMS} = "win-64"
${Env:PIXI_PROMPT} = "(deno_sample) "
$old_prompt = $function:prompt
function prompt {"(deno_sample) $($old_prompt.Invoke())"}
Env:Pathを見ると、ワークスペースの情報だけではなく、私の
[tasks.java]
cmd = "java -version"
[tasks.gcc]
cmd = "gcc --version"
[tasks.qemu]
cmd = "qemu-system-x86_64 --version"
[tasks.find_text]
cmd = """ find '"world"' *.txt """
[tasks.ls]
cmd = "powershell -command ls -name"
PS C:\⋯> pixi run java
Pixi task (java): java -version
java version "20.0.1" 2023-04-18
Java(TM) SE Runtime Environment (build 20.0.1+9-29)
Java HotSpot(TM) 64-Bit Server VM (build 20.0.1+9-29, mixed mode, sharing)
PS C:\⋯> pixi run gcc
Pixi task (gcc): gcc --version
gcc.exe (x86_64-win32-seh-rev1, Built by MinGW-Builds project) 14.2.0
Copyright (C) 2024 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
PS C:\⋯> pixi run qemu
Pixi task (qemu): qemu-system-x86_64 --version
QEMU emulator version 9.0.0 (v9.0.0-12054-g923cf646f4)
Copyright (c) 2003-2024 Fabrice Bellard and the QEMU Project developers
PS C:\⋯> pixi run find_text
Pixi task (find_text): find '"world"' *.txt
Access denied - \
---------- DIRNAMES.TXT
---------- HELLO_WORLD.TXT
---------- 放膽文.TXT
PS C:\⋯> pixi run ls
Pixi task (ls): powershell -command ls -name
.pixi
dir1
dir2
dir3
new_dir
.gitattributes
.gitignore
dirnames.txt
hello_world.txt
pixi.lock
pixi.toml
放膽文.txt
これらのタスクは完全に私の
なおこの内、
一方でfindやpowershellは、C:\Windows\System32に存在する実行ファイルである。findやlsコマンドは存在するが、実体が全く別物であるため、オプションの使い方が異なっており、結局互換性はない。
補遺2. :タスクごとに分けた記述
本記事では一貫して、[tasks]の下にタスクを記述した。しかしタスクの定義が複雑になると、
[tasks]
division = { cmd = """python -c '''
{% if not b == "0" %}
print({{ a }} / {{ b }})
{% else %}
print("Error: Division by zero")
{% endif %}
'''
""", args = [
{ "arg" = "a", "default" = "1" },
{ "arg" = "b", "default" = "1" }
] }
mkdir_src = { cmd = "mkdir -p src" }
create_main_py_cache = { cmd = "echo 'import sys\n\nprint(sys.version)' > src/main.py", depends-on = ["mkdir_src"], outputs = ["src/main.py"] }
run_main_py_cache = { cmd = "python src/main.py", depends-on = ["create_main_py_cache"], inputs = ["src/main.py"] }
このような場合、一つのタスクを次のようにして個々に記述することで、改行できるようになり、若干読みやすくなる。
[tasks]
mkdir_src = { cmd = "mkdir -p src" }
[tasks.division]
cmd = """python -c '''
{% if not b == "0" %}
print({{ a }} / {{ b }})
{% else %}
print("Error: Division by zero")
{% endif %}
'''"""
args = [
{ "arg" = "a", "default" = "1" },
{ "arg" = "b", "default" = "1" }
]
[tasks.create_main_py_cache]
cmd = "echo 'import sys\n\nprint(sys.version)' > src/main.py"
depends-on = ["mkdir_src"]
outputs = ["src/main.py"]
[tasks.run_main_py_cache]
cmd = "python src/main.py"
depends-on = ["create_main_py_cache"]
inputs = ["src/main.py"]
Discussion