Tutorial: Building a Python package#
In this tutorial, we will show you how to create a simple Python package with pixi.
Why is this useful?#
Pixi builds upon the conda ecosystem, which allows you to create a Python environment with all the dependencies you need. Unlike PyPI, the conda ecosystem is cross-language and also offers packages written in Rust, R, C, C++ and many other languages.
By building a Python package with pixi, you can:
- manage Python packages and packages written in other languages in the same workspace
- build both conda and Python packages with the same tool
In this tutorial we will focus on point 1.
Let's get started#
First, we create a simple Python package with a pyproject.toml
and a single Python file.
The package will be called rich_example
, so we will create the following structure:
The Python package has a single function main
.
Calling that, will print a table containing the name, age and city of three people.
from dataclasses import dataclass, fields
from rich.console import Console
from rich.table import Table
@dataclass
class Person:
name: str
age: int
city: str
def main() -> None:
console = Console()
people = [
Person("John Doe", 30, "New York"),
Person("Jane Smith", 25, "Los Angeles"),
Person("Tim de Jager", 35, "Utrecht"),
]
table = Table()
for column in fields(Person):
table.add_column(column.name)
for person in people:
table.add_row(person.name, str(person.age), person.city)
console.print(table)
The metadata of the Python package is defined in pyproject.toml
.
[project]
dependencies = ["rich"]
name = "rich_example"
requires-python = ">= 3.11"
scripts = { rich-example-main = "rich_example:main" }
version = "0.1.0"
[build-system]
build-backend = "hatchling.build"
requires = ["hatchling"]
Adding a pixi.toml
#
What we have in the moment, constitutes a full Python package. It could be uploaded to PyPI as-is.
However, we still need a tool to manage our environments and if we want other pixi projects to depend on our tool, we need to include more information.
We will do exactly that by creating a pixi.toml
.
Note
The pixi manifest can be in its own pixi.toml
file or integrated in pyproject.toml
In this tutorial, we will use pixi.toml
.
If you want everything integrated in pyproject.toml
just copy the content of pixi.toml
in this tutorial to your pyproject.toml
and append tool.pixi
to each table.
Let's initialize a pixi project.
We pass --format pixi
in order to communicate to pixi, that we want a pixi.toml
rather than extending pyproject.toml
.
This is the content of the pixi.toml
:
[workspace]
channels = ["https://prefix.dev/conda-forge"]
platforms = ["win-64", "linux-64", "osx-arm64", "osx-64"]
preview = ["pixi-build"]
[dependencies]
rich_example = { path = "." }
[tasks]
start = "rich-example-main"
[package]
name = "rich_example"
version = "0.1.0"
[package.build]
backend = { name = "pixi-build-python", version = "*" }
channels = [
"https://prefix.dev/pixi-build-backends",
"https://prefix.dev/conda-forge",
]
[package.host-dependencies]
hatchling = "==1.26.3"
[package.run-dependencies]
rich = ">=13.9.4,<14"
When we now run pixi run start
, we get the following output:
┏━━━━━━━━━━━━━━┳━━━━━┳━━━━━━━━━━━━━┓
┃ name ┃ age ┃ city ┃
┡━━━━━━━━━━━━━━╇━━━━━╇━━━━━━━━━━━━━┩
│ John Doe │ 30 │ New York │
│ Jane Smith │ 25 │ Los Angeles │
│ Tim de Jager │ 35 │ Utrecht │
└──────────────┴─────┴─────────────┘
Conclusion#
In this tutorial, we created a pixi package based on Python. It can be used as-is, to upload to a conda channel or to PyPI. In another tutorial we will learn how to add multiple pixi packages to the same workspace and let one pixi package use another.
Thanks for reading! Happy Coding 🚀
Any questions? Feel free to reach out or share this tutorial on X, join our Discord, send us an e-mail or follow our GitHub.