Puppy
Your new best friend. Puppy is the easiest way to get started with modern python on any platform, install packages in virtual environments, and contribute to external projects.
Install / Use
/learn @liquidcarbon/PuppyREADME
Puppy
<center>tested with: 🐍 python 3.10–3.14 | ✨pixi 0.63.2 | 🟣 uv 0.9.27</center>Puppy helps you set up and manage your python projects. It's the easiest way to get started with modern python on any platform, install packages in virtual environments, and contribute to external projects.
<img alt="Puppy Logo" src="https://github.com/liquidcarbon/puppy/assets/47034358/da604ebd-4ce3-4e5d-b88b-ef46de7367fc" width="270">Get started
You need only curl / iwr and an empty folder; pup will handle the rest, with a little help from its powerful friends pixi and uv.
Linux
curl -fsSL https://pup-py-fetch.hf.space | bash
Windows
iex (iwr https://pup-py-fetch.hf.space).Content
One Installer To Rule Them All
[!NOTE] This installer is hosted on HuggingFace. It's been reliable for the last 8 months or so, but every now then it returns bits of broken HTML, in that case use
https://raw.githubusercontent.com/liquidcarbon/puppy/main/pup.shorhttps://raw.githubusercontent.com/liquidcarbon/puppy/main/pup.ps1instead.
The pup-py-fetch API accepts query parameters that allow specifying the exact environment recipe you want to build:
python: 3.10 through 3.13pixi: comma-separated list of pixi/Conda dependenciesclone: comma-separated list of GitHub repos to clone and build in a virtual environment- virtual environments: all other query parameters with comma-separated package names, including:
- regular PyPI packages (no support for version pinning at this time)
- packages from GitHub repos using
<username>/<reponame>(only GitHub at this time; repo must contain must contain buildablepyproject.tomlin its root)
[!NOTE] As of Dec 2024, many packages still do not support python 3.13; thus, the default version in puppy is 3.12.
The URLs above return installation scripts. You can mix and match query parameters, unlocking single-command recipes for complex builds:
curl -fsSL "https://pup-py-fetch.hf.space?pixi=marimo&env1=duckdb,pandas&env2=cowsay" | bash
iex (iwr "https://pup-py-fetch.hf.space?python=3.11&pixi=marimo&tables=duckdb,pandas,polars").Content
Or just grab the base build and use pup commands:
https://github.com/user-attachments/assets/9cdd5173-5358-404a-84cc-f569da9972f8
How It Works
Puppy is a transparent wrapper around pixi and uv, two widely used Rust-based tools that belong together.
Puppy can be used as a CLI in a Linux or Windows shell, or as a module in any python shell/script/notebook.
Installing puppy preps the folder to house python, in complete isolation from system or any other python on your system:
- 🐍 this folder is home to one and only one python executable, managed by pixi
- ✨ puppy installs pixi; pixi installs core components: python, uv, click
- ⚙ Bash or Powershell runner/installer is placed into
~/.pixi/bin(the only folder that goes on PATH) - 🐶
pup.pyis the python/click CLI that wraps pixi and uv commands - 🟣
pup newandpup adduse uv to handle projects, packages and virtual environments - 📀
pup cloneandpup synchelp build environments from externalpyproject.tomlproject files
Using pup as a Module: pup.fetch
Pup can help you construct and activate python projects interactively, such as from (i)python shells, jupyter notebooks, or marimo notebooks.
Pup scans for folders containing valid pyproject.toml and python executable inside .venv folder. If a venv does not exist, pup can create it.
a@a-Aon-L1:~/Desktop/puppy$ .pixi/envs/default/bin/python
Python 3.12.7
>>> import pup; pup.fetch()
[2024-10-26 16:50:37] 🐶 said: woof! run `pup.fetch()` to get started
[2024-10-26 16:50:37] 🐶 virtual envs available: ['tbsky', 't1/web', 't2', 'tmpl', 'test-envs/e1']
Choose venv to fetch: t1/web
[2024-10-26 16:51:56] 🐶 heard: pup list t1/web
{
"t1/web": [
"httpx>=0.27.2",
"requests>=2.32.3"
]
}
[2024-10-26 16:51:56] fetched packages from 't1/web': /home/a/Desktop/puppy/t1/web/.venv/lib/python3.12/site-packages added to `sys.path`
Now the "kernel" t1/web is activated. In other words, packages installed t1/web/.venv are available on sys.path.
[!NOTE] Folders inside pup's home folder are scanned recursively, and nested paths are supported. Symlinks are not followed.
Need to install more packages on the go, or create a new venv? Just provide the destination, and list of packages.
pup.fetch("myenv") # activate existing environment
pup.fetch("myenv", quiet=True) # activate quietly (output suppressed)
pup.fetch("myenv", "duckdb", "pandas", "pyarrow") # create/update venv, install packages, activate
Here is the signature of pup.fetch():
def fetch(
venv: str | None = None,
*packages: Optional[str],
site_packages: bool = True,
root: bool = False,
quiet: bool = False,
) -> None:
"""Create, modify, or fetch (activate) existing venvs.
Activating an environment means placing its site-packages folder on `sys.path`,
allowing to import the modules that are installed in that venv.
`venv`: folder containing `pyproject.toml` and installed packages in `.venv`
if venv does not exist, puppy will create it, install *packages,
and fetch newly created venv
`*packages`: names of packages to `pup add`
`site_packages`: if True, appends venv's site-packages to `sys.path`
`root`: if True, appends venv's root folder to `sys.path`
(useful for packages under development)
`quiet`: suppress output
"""
With root=True, you also add new project's root folder to your environment, making its modules available for import.
This is useful for working with projects that themselves aren't yet packaged and built.
You also have the option to omit the site-packages folder with site_packages=False.
pixi run python
Python 3.12.7 | packaged by conda-forge | (main, Oct 4 2024, 16:05:46) [GCC 13.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import pup; pup.fetch("test-only-root", root=True, site_packages=False)
[2024-11-22 13:10:49] 🐶 said: woof! run `pup.fetch()` to get started
[2024-11-22 13:10:49] 🐶 virtual envs available: ['gr']
[2024-11-22 13:10:49] 🐶 heard: pup new test-only-root
[2024-11-22 13:10:49] 🐶 said: pixi run uv init /home/a/puppy/test-only-root -p /home/a/puppy/.pixi/envs/default/bin/python --no-workspace
Initialized project `test-only-root` at `/home/a/puppy/test-only-root`
[2024-11-22 13:10:49] 🐶 said: pixi run uv venv /home/a/puppy/test-only-root/.venv -p /home/a/puppy/.pixi/envs/default/bin/python
Using CPython 3.12.7 interpreter at: .pixi/envs/default/bin/python
Creating virtual environment at: test-only-root/.venv
Activate with: source test-only-root/.venv/bin/activate
Specify what to install:
[2024-11-22 13:10:50] 🐶 virtual envs available: ['gr', 'test-only-root']
[2024-11-22 13:10:50] fetched packages from 'test-only-root': /home/a/puppy/test-only-root added to `sys.path`
[2024-11-22 13:10:50] 🐶 heard: pup list test-only-root
{
"test-only-root": []
}
>>> import hello; hello.main() # `hello.py` is included in uv's project template
Hello from test-only-root!
Puppy & Environments in Notebooks
[!NOTE] Conda or PyPI packages installed with
pixi add ...always remain onsys.pathand stay available across all environments. Though one could exclude them, I have yet to find a reason to do so.
Jupyter
There's a good chance you're confused about how Jupyter kernels work and find setting up kernels with virtual environments too complicated to bother. Puppy's v1 was addressing that problem, but in v2 (current version) this is taken care of by pup.fetch. Here's the gist:
- install ONE instance of jupyter with
pixi add jupyterper major version of python - run it with
pixi run jupyter laborpixi run jupyter notebook - use
pup.fetchto build and activate your environment - THAT'S IT!
For details, scan through the previous section. In brief, pup.fetch creates/modifies and/or activates your venv by appending its folder to sys.path. This is pretty very similar to how venvs and kernels work. A jupyter kernel is a pointer to a python executable. Within a venv, the executable .venv/bin/python is just a symlink to the parent python - in our case, to pixi's python. The activation and separation of packages is achieved by manipulating sys.path to include local site-packages folder(s).
Marimo
With marimo, you have more options: Unified environment management for any computational notebooks - no more Jupyter kernels!
Where Pixi Shines 🎇
UV is rightfully getting much love in the community, but Pixi is indispensable for:
- Conda channels support
- Setting up really complex build environments for multi-language projects. For example, try pulling together what's done here in one API call (python, NodeJS, pnpm, clon
