Skip to main content

How to Run a Python Script with uv run

· 9 min read
Jagdish Kumawat
Founder @ Dewiride

You added a package with uv, ran your script with python3, and got ModuleNotFoundError. The package is installed, just not in the Python you started. uv run runs everything inside the project's own environment, and brings that environment up to date first. This guide explains the command's syntax first, then runs a small script, a project command and a tool in a hello-world project, with real output from uv 0.13.8.

Syntax​

Syntax
uv run [OPTIONS] <COMMAND> [ARGS]...
PartWhat it means
uv runRuns a command in the project's environment, after making sure the environment is up to date
[OPTIONS]uv's own settings. Square brackets mean you can leave them out
<COMMAND>What to run: a Python file, a command from the project's pyproject.toml, or a tool installed in the project. Angle brackets mean you must fill it in
[ARGS]...Anything you type after the command. It goes to your program, not to uv

uv's command reference states the two rules that trip people up: "uv run file.py is equivalent to uv run python file.py", and "All options to uv must be provided before the command".

The forms you'll use most:

FormWhat it runs
uv run <file>.pyA Python file, with the project's Python
uv run <file>.py <args>The same file, with arguments for it
uv run <command>A command listed under [project.scripts] in pyproject.toml
uv run <tool> <args>A tool installed in the project, such as pytest or Ruff
uv run python <args>Python itself, for example uv run python --version

Prerequisites​

uv run works the same in Terminal (macOS), PowerShell (Windows) and Linux shells. Only the command for your computer's own Python differs, and the tabs in Step 2 show both.

Step 1: Write a Small Script​

The example script greets someone in a box drawn by Rich, the package the project added. Save it as hello.py in the project folder, next to pyproject.toml:

hello-world/hello.py
import sys

from rich import print
from rich.panel import Panel

name = sys.argv[1] if len(sys.argv) > 1 else "world"
print(Panel.fit(f"Hello, {name}!"))

The hello.py script in a macOS-style code window: it imports sys, Rich's print and Panel, takes the name from the first command-line argument or uses world, and prints Hello with that name inside a Rich panel.

LineWhat it does
import sysPython's built-in sys module. Its sys.argv list holds the script's name followed by the words typed after it
from rich import printRich's print, which can draw boxes and colors. It replaces the normal print in this file
from rich.panel import PanelRich's box
name = ...The first word after the file name, or "world" when there isn't one
print(Panel.fit(...))Prints the greeting in a box that fits the text

The project now looks like this:

hello-world/
hello-world/
├── .git/
├── .venv/
├── .gitignore
├── .python-version
├── README.md
├── hello.py
├── pyproject.toml
├── src/
│ └── hello_world/
│ └── __init__.py
└── uv.lock

Step 2: See Why Your Computer's Python Can't Find Rich​

uv add installed Rich into the project's .venv folder, not into the Python on your computer. Run the script with your computer's Python first:

Terminal
python3 hello.py
Output (macOS)
Traceback (most recent call last):
File "/Users/you/source/hello-world/hello.py", line 3, in <module>
from rich import print
ModuleNotFoundError: No module named 'rich'

Now run the same file with uv run:

Terminal
uv run hello.py
Output
╭───────────────╮
│ Hello, world! │
╰───────────────╯

A terminal where python3 hello.py fails with ModuleNotFoundError: No module named 'rich', while uv run hello.py prints Hello, world! in a box, and uv run hello.py Sam prints Hello, Sam!

Same computer, same folder: uv run used the Python in .venv, where Rich is installed. The longer uv run python hello.py printed exactly the same box.

Step 3: Pass Arguments to Your Script​

Everything after the file name goes to the script:

Terminal
uv run hello.py Sam
Output
╭─────────────╮
│ Hello, Sam! │
╰─────────────╯

That includes words that look like uv's own options. --verbose is one of uv's options, but here it comes after the file name, so uv hands it to the script, which greets it:

Terminal
uv run hello.py --verbose
Output
╭───────────────────╮
│ Hello, --verbose! │
╰───────────────────╯

To give an option to uv, put it before the command, as in the reference's own example, uv run --verbose foo.

Step 4: Run a Project Command​

Commands listed under [project.scripts] in pyproject.toml become real commands inside the environment. uv init gave the project one:

hello-world/pyproject.toml (excerpt)
[project.scripts]
hello-world = "hello_world:main"

It runs the main() function in src/hello_world/__init__.py:

Terminal
uv run hello-world
Output
Hello from hello-world!

Step 5: Run a Tool Installed in the Project​

Packages that come with their own commands are run the same way. Ruff, added as a development tool, checks hello.py for mistakes:

Terminal
uv run ruff check hello.py
Output
All checks passed!

Python is a command too. This shows the project's Python version:

Terminal
uv run python --version
Output
Python 3.15.2

Step 6: Watch uv run Update the Environment​

Before it runs anything, uv run checks that .venv matches pyproject.toml and uv.lock, and fixes it if not. uv's reference puts it this way: "the project environment will be created and updated before invoking the command". To see it, open pyproject.toml and change the project's version from 0.1.0 to 0.2.0:

hello-world/pyproject.toml (excerpt)
version = "0.2.0"

Then run the project command again:

Terminal
uv run hello-world
Output
Built hello-world @ file:///Users/you/source/hello-world
Uninstalled 1 package in 2ms
Installed 1 package in 3ms
Hello from hello-world!

The first three lines are uv rebuilding your project, because pyproject.toml changed; the last line is your program. Run it once more and there's nothing to update, so you get only Hello from hello-world!. The same happens when a teammate adds a package and you pull their change: your next uv run installs it before running anything.

Common Mistakes​

MistakeWhat happensDo this instead
Running python3 hello.py in a uv projectModuleNotFoundError: No module named 'rich', although uv add installed ituv run hello.py
Typing uv run --version to see Python's versionerror: unexpected argument '--version' founduv run python --version
Putting a uv option after the command, as in uv run hello.py --verboseuv passes it to your program insteadPut it before the command: uv run --verbose hello.py
Running a project command from another foldererror: Failed to spawn: hello-world with cause: No such file or directory (os error 2)cd into the project folder first

Troubleshooting​

SymptomLikely causeFix
error: Failed to spawn: hello-wroldThe command name is misspelled, or you're outside the project folderCheck the spelling against [project.scripts] in pyproject.toml, and run from the project folder
No module named hello_world.__main__; 'hello_world' is a package and cannot be directly executedYou ran the package with uv run python -m hello_worldRun the command from [project.scripts] instead: uv run hello-world
Built … Uninstalled … Installed before your program's outputuv is updating the environment after pyproject.toml changedExpected

FAQ​

Is uv run hello.py the same as uv run python hello.py?​

Yes. uv's reference says so, and both printed the same box here. The shorter form is all you need.

Do I still need to activate the virtual environment?​

No. uv run uses .venv directly. You can still activate it if you prefer, but you don't have to.

Does uv run work in PowerShell?​

Yes. Every uv run command on this page is the same in PowerShell; only running your computer's own Python differs (python instead of python3).

Conclusion​

uv run [OPTIONS] <COMMAND> [ARGS]... runs a command with the project's environment. python3 hello.py used your computer's Python, which doesn't have Rich, so it failed. uv run hello.py used the project's .venv and passed Sam on to the script. The same works for project commands such as hello-world and for tools such as ruff, and every run brings the environment up to date first.

Additional Resources​