Pixi Task Decorator¶
Python callables decorated with @task.pixi run inside a Pixi environment.
The decorator is registered on Airflow's task object once the provider is installed.
Parameters¶
@task.pixi accepts every PixiOperator argument, plus:
multiple_outputs- If set, a returned dict is unrolled to multiple XCom values, with the keys as XCom keys.
Defaults to
False.
The environment is chosen the same way as for the operator: exactly one of pixi_project_path,
pixi_toml_path, or an inline manifest (dependencies / pypi_dependencies). See
Choosing the environment. A relative project path is
relative to the DAG file, and lock_mode="locked" installs a project from its pixi.lock without
updating it.
Usage example¶
# Defined in the DAG file, so it reaches the environment as source.
@task.pixi(**ENV)
def double(x: int) -> dict:
import sys
print("doubling", x)
return {"value": x * 2, "prefix": sys.prefix}
With an existing project and one of its environments:
from airflow.sdk import dag, task
@dag
def my_dag():
@task
def epochs() -> int:
return 3
@task.pixi(pixi_project_path="/path/to/pixi/project", environment="cuda")
def train(epochs: int) -> float:
import torch
return torch.rand(epochs).mean().item()
train(epochs())
my_dag()
Writing the function¶
Like @task.virtualenv, the function's source is shipped to the environment and run there, so:
- Imports go inside the function. The environment does not have the DAG file's imports, and may not have Airflow installed at all.
- No variables from enclosing functions. A function that uses one is rejected when the DAG is parsed; pass the value as an argument instead.
async defworks too. The environment awaits the coroutine withasyncio.run; the event loop exists only for that call.- Arguments and the return value are serialized, as JSON by default or with
serializer="pickle". See Arguments and return values. -
Context values arrive as parameters, as for
@task.virtualenv:ds,params,run_id,logical_dateand the other keys listed in Airflow context, as JSON values. Dates are ISO 8601 strings. Give these parameters a default, as for any TaskFlow function:@task.pixi(pypi_dependencies=["pandas", "pyarrow"]) def report(table: str, ds=None, params=None) -> int: import pandas as pd return len(pd.read_parquet(f"{params['root']}/{table}/{ds}.parquet"))ti,dag_runand other Airflow objects don't reach the environment, andget_current_context()isn't available there. -
An exception fails the task with
PixiCallableError, such astrain raised ValueError: no rows, after its traceback is printed to the task log. To skip the task instead, exit with a code listed inskip_on_exit_code, for examplesys.exit(99). See Errors, skipping and timeouts.
Task decorators such as @task.pixi, @setup, @teardown, @task.skip_if and @task.run_if are
removed from the shipped source, and so is the decorator of a provider that builds on @task.pixi
(see Building on the Pixi Operator). Line numbers are kept, so a traceback raised
inside the environment points at the right line of the DAG file.