Skip to main content

Scripts

Notebooks are good for exploring data. For processing you run more than once, or hand over to someone else, write a script instead:

  • it takes its inputs as arguments, so the same code runs on the next dataset without editing
  • it runs unattended, from a scheduler or another script
  • it stops with an error code when something goes wrong, instead of leaving a half-run notebook
  • changes to it show up as a readable diff in version control

A script that carries its dependencies

This script subtracts a baseline run from a scenario run, using mikeio.generic.diff:

diff.py
"""Write the difference between two dfs files (scenario - baseline)."""
# /// script
# requires-python = "==3.12.*"
# dependencies = ["mikeio==3.3.0"]
# [tool.uv]
# exclude-newer = "2026-09-23T00:00:00Z"
# ///

import argparse
from collections.abc import Sequence

from mikeio.generic import diff


def main(argv: Sequence[str] | None = None) -> None:
    """Parse the command line and write the difference file."""
    parser = argparse.ArgumentParser(description=__doc__)
    parser.add_argument("scenario", help="scenario result file")
    parser.add_argument("baseline", help="baseline result file")
    parser.add_argument("output", help="output file")
    args = parser.parse_args(argv)

    diff(args.scenario, args.baseline, args.output)
    print(f"Created {args.output}")


if __name__ == "__main__":
    main()

The comment block at the top is inline script metadata. It lists the Python version and packages the script needs. uv reads it, creates an environment with exactly those packages, and runs the script in it. You don’t need to install MIKE IO first, and the script doesn’t touch any other environment on the machine.

Run it

uv can run the script straight from this site:

uv run https://dhi.github.io/mikeio/scripts/diff.py scenario.dfsu baseline.dfsu difference.dfsu

or from a local copy:

uv run diff.py scenario.dfsu baseline.dfsu difference.dfsu

Run it with --help to see the arguments.

Pin the versions

mikeio==3.3.0 fixes the MIKE IO version, but not the versions of the packages MIKE IO depends on, such as NumPy and pandas. A new release of one of those can change the result or break the script. exclude-newer makes uv ignore every package released after the given date, so the script resolves to the same versions every time it runs.

requires-python = "==3.12.*" fixes the Python version too. Without it, uv uses the newest Python on the machine, and packages pinned to an earlier date may have no build for a Python released after it. uv downloads Python 3.12 if it isn’t installed.

To write or update the header, use:

uv add --script diff.py "mikeio==3.3.0"

For an exact record of every package version, uv lock --script diff.py writes a diff.py.lock file next to the script. Share both files.

An app in one file

The same header works for a script with a user interface. This one is a Streamlit app: upload a dfs0 file, plot Items, trim the time window and download the result as dfs0 or CSV. Without a file it shows synthetic tide-station data.

uv run https://dhi.github.io/mikeio/scripts/dfs0_app.py

The app opens in the browser and runs on your own machine, so there is no server to set up and your files are not uploaded anywhere. The first run takes about a minute while uv fetches the packages.

Streamlit apps are normally started with streamlit run app.py. The block at the end of dfs0_app.py does that for you, so uv run is enough:

if __name__ == "__main__":
    if st.runtime.exists():
        main()
    else:
        # Started with `uv run dfs0_app.py`: hand over to `streamlit run` on this file.
        from streamlit.web import cli

        sys.argv = ["streamlit", "run", __file__, *sys.argv[1:]]
        sys.exit(cli.main())

Projects with several scripts

When a project has several scripts that share dependencies, give the project its own environment instead:

uv init my-project
cd my-project
uv add mikeio
uv run process.py

This writes the dependencies to pyproject.toml and the exact versions to uv.lock. Commit both. Each project then keeps the versions it was developed with, and upgrading MIKE IO for one project cannot break another. See working on projects in the uv documentation.