|
| 1 | +--- |
| 2 | +:og:description: Learn how to run standalone Python scripts with Hatch using |
| 3 | + inline metadata so dependencies and Python versions are managed |
| 4 | + automatically. |
| 5 | +:og:title: Run standalone Python scripts with Hatch |
| 6 | +--- |
| 7 | + |
| 8 | +# Run standalone Python scripts with Hatch |
| 9 | + |
| 10 | +Python supports inline metadata for scripts (a feature added in 2024). This makes it possible to run |
| 11 | +standalone scripts with dependencies and Python versions managed |
| 12 | +automatically. |
| 13 | + |
| 14 | +Many tools support this workflow, including PDM, Hatch, and uv. In this |
| 15 | +tutorial, we focus on Hatch and UV. The same metadata format can also be used with |
| 16 | +other tools. |
| 17 | + |
| 18 | +:::{seealso} |
| 19 | + |
| 20 | +* [Hatch: How to run Python scripts](https://hatch.pypa.io/latest/how-to/run/python-scripts/) |
| 21 | +* [uv: Running scripts](https://docs.astral.sh/uv/guides/scripts/#creating-a-python-script) |
| 22 | +::: |
| 23 | + |
| 24 | +## How to create a reproducible script |
| 25 | + |
| 26 | +Sometimes you want to share or run a single script without creating a full |
| 27 | +package. To do this, you can use inline script metadata. This format lets you |
| 28 | +specify dependencies and Python versions at the top of your script in a |
| 29 | +comment block. |
| 30 | + |
| 31 | +When you add metadata at the top of a script, Hatch (or PDM or uv) will use |
| 32 | +that metadata to: |
| 33 | + |
| 34 | +* Create an isolated virtual Python environment for that script. |
| 35 | +* Install the dependencies listed in the script into that environment. |
| 36 | +* Use the required Python version that you specify in the metadata. |
| 37 | + |
| 38 | +This approach is useful for workflows that you want to make reproducible, but |
| 39 | +that do not need to become full Python packages. |
| 40 | + |
| 41 | +## Why use Hatch for scripts? |
| 42 | + |
| 43 | +Inline metadata helps you make scripts reproducible. Anyone can run your |
| 44 | +script without manually creating a new environment or guessing which |
| 45 | +dependencies it needs. Hatch takes care of installing dependencies and using |
| 46 | +the correct Python version. |
| 47 | + |
| 48 | +## How to add inline metadata to your script |
| 49 | + |
| 50 | +You will use Hatch in this example, but you can also use uv if that is your |
| 51 | +preferred tool. |
| 52 | + |
| 53 | +First, create a new file named `script.py` with the block below at the top. |
| 54 | +The metadata block starts with `# /// script` and ends with `# ///`. |
| 55 | +Everything in between must be TOML metadata written as comments. |
| 56 | + |
| 57 | +In the example below, the script requires Python 3.11 or newer, and NumPy is |
| 58 | +declared as a dependency. |
| 59 | + |
| 60 | +```python |
| 61 | +# /// script |
| 62 | +# requires-python = ">=3.11" |
| 63 | +# dependencies = [ |
| 64 | +# "numpy", |
| 65 | +# ] |
| 66 | +# /// |
| 67 | + |
| 68 | +import numpy as np |
| 69 | + |
| 70 | +temperatures_c = np.array([12.4, 13.1, 14.8, 15.2, 16.0, 14.4, 13.7]) |
| 71 | +mean_temp = np.mean(temperatures_c) |
| 72 | +anomalies = temperatures_c - mean_temp |
| 73 | + |
| 74 | +print(f"Mean temperature: {mean_temp:.2f} C") |
| 75 | +print("Temperature anomalies:", np.round(anomalies, 2)) |
| 76 | +``` |
| 77 | + |
| 78 | +## Run the script with Hatch |
| 79 | + |
| 80 | +Open your terminal and change to the directory where `script.py` lives. |
| 81 | +Then run: |
| 82 | + |
| 83 | +```bash |
| 84 | +hatch run script.py |
| 85 | +``` |
| 86 | + |
| 87 | +On first run, Hatch will create an environment and install dependencies. On |
| 88 | +later runs, Hatch will reuse that environment so startup is faster. |
| 89 | + |
| 90 | +:::{note} |
| 91 | +The environment name is based on the script path. If you move the script to a |
| 92 | +new location, Hatch will treat it as a new script environment. |
| 93 | +::: |
| 94 | + |
| 95 | +## Optional: configure script environment behavior |
| 96 | + |
| 97 | +You can control script-specific Hatch behavior in the same metadata block. |
| 98 | +For example, to use `pip` instead of `uv` as the installer: |
| 99 | + |
| 100 | +```python |
| 101 | +# /// script |
| 102 | +# requires-python = ">=3.11" |
| 103 | +# dependencies = ["numpy"] |
| 104 | +# |
| 105 | +# [tool.hatch] |
| 106 | +# installer = "pip" |
| 107 | +# /// |
| 108 | +``` |
| 109 | + |
| 110 | +:::{admonition} Run the same script with uv |
| 111 | + |
| 112 | +If you prefer uv, you can run the same inline-metadata script with: |
| 113 | + |
| 114 | +```bash |
| 115 | +uv run script.py |
| 116 | +``` |
| 117 | + |
| 118 | +The same `# /// script` metadata block works with uv, including |
| 119 | +`requires-python` and `dependencies`. |
| 120 | + |
| 121 | +For more on using uv to run scripts, see the guide: |
| 122 | +[Running scripts with uv](https://docs.astral.sh/uv/guides/scripts/#creating-a-python-script). |
| 123 | +::: |
| 124 | + |
| 125 | +## When to use scripts vs. packages |
| 126 | + |
| 127 | +You may be wondering when to use scripts versus creating a package. |
| 128 | + |
| 129 | +This depends on your use case. Scripts are often useful when: |
| 130 | + |
| 131 | +* You have one small task, or a specific workflow that is not generalizable. |
| 132 | +* Your workflow is still evolving, but you want to run it in a reproducible |
| 133 | + environment. |
| 134 | +* You want reproducible dependencies quickly. |
| 135 | +* You are sharing a single file with collaborators. |
| 136 | + |
| 137 | +Create a full package when: |
| 138 | + |
| 139 | +* You are building reusable modules for multiple projects. |
| 140 | +* You need tests, documentation, releases, and long-term maintenance. |
| 141 | +* Your codebase is growing beyond one or two scripts. |
| 142 | + |
| 143 | +:::{seealso} |
| 144 | + |
| 145 | +* [Get to know Hatch](get-to-know-hatch.md) |
| 146 | +* [Create a Python package](create-python-package.md) |
| 147 | +* [Command line reference guide](command-line-reference.md) |
| 148 | +::: |
0 commit comments