Cloudscale Logo

Engineering Blog

Zurück
Publiziert am 22. August 2025 von

Die Magie von uv in IntelliJ IDEA

Dieser Inhalt ist nur auf Englisch verfügbar:

Learn how to effectively use uv package manager within IntelliJ IDEA for Python projects, with practical setup steps and workarounds for current limitations.

Recently, I took the time to delve into the uv package and project manager, which you've likely heard of if you're involved in the Python community in any way. uv is maintained by the same company as the Ruff linter and code formatter. The command-line interface (CLI) command felt fast and intuitive. But of course, I wanted to use IntelliJ IDEA for my project and at the same time take advantage of uv's features. This process was much less straightforward than I had expected, since while there is uv support in IntelliJ IDEA, it's currently not as well integrated as it could be.

That's why I have decided to write a blog post about how I currently set up my uv-based projects, primarily for my future self as a reference - but I guess it could also be helpful to others even if you have no prior experience with uv. In that sense, this blog is opinionated and just reflects my current approach.

It's important to note that this is a snapshot, everything might change with future versions.

The Goal and Intro to this Guide

For me, these are the minimal requirements for a good development environment:

  • No, or at least almost no, typing of commands into the terminal. Instead, I want to rely on Run Configurations and similar first-class IDE features.
  • An exception to the above point is the initialization of a project, where I actually prefer the CLI.
  • Imports must be correctly resolved within the IDE
  • Debugger must work for the production as well as test code
  • IDE is aware of the Python dependencies installed in the Project

If you want to follow along, please prepare the following:

  • A uv binary in your PATH (see Installing uv)
  • An IntelliJ IDEA installation with the following plugins installed: Python and Python Community Edition. PyCharm should work as well, but I did not test it.
  • Installed Python interpreter is optional, we'll use uv to set one up.

As of this writing the uv version I am using is 0.8.0, together with IntelliJ IDEA 2025.2 and version 252.23892.458 of the two Python plugins.

Setting Up a Project with uv

In this section, we will set up a project with uv and add some code. The goal is to see uv and some of its highlights in action.

Let's go ahead and create a new project. I pass the --package flag to uv init since I prefer to use src-layout.

mkdir my-hello-project
cd my-hello-project
uv init --package

The working tree now looks like this:

.
|-- .git [truncated]
|-- .gitignore
|-- .python-version
|-- pyproject.toml
|-- README.md
`-- src
    `-- my_hello_project
        `-- __init__.py

Since this is pretty boring, let's add some code to the project, including two dependencies:

# Empty the __init__.py file
cat << EOF >  src/my_hello_project/__init__.py
EOF

# Add some non-trivial code that requires a dependency
cat << EOF > src/my_hello_project/hello.py
import cowsay
import sys
import random


def run_hello() -> None:
    characters = ["cow", "tux"]
    random_char = random.choice(characters)
    python_version, *_ = sys.version.split()
    print(cowsay.get_output_string(random_char, f"Running on {python_version}"))
EOF

# Make my_hello_project a module
cat << EOF > src/my_hello_project/__main__.py
from my_hello_project.hello import run_hello

if __name__ == "__main__":
    run_hello()
EOF

# Create tests
mkdir tests
cat << EOF > tests/test_hello.py
import sys

import pytest

from my_hello_project.hello import run_hello


def test_hello(capsys: pytest.CaptureFixture) -> None:
    # act
    run_hello()

    # assert
    major, minor, micro, *_ = sys.version_info
    expected = f"{major}.{minor}.{micro}"
    captured = capsys.readouterr()
    assert expected in captured.out
EOF

Now we use uv to add the two dependencies to pyproject.toml:

uv add cowsay
uv add --dev pytest

And now we are ready for some action. Let's run the tests:

uv run -m pytest      # or -m my_hello_project to run the application

The cool thing is that in this command multiple things happen:

  • A python interpreter was downloaded if none was found in your PATH.
  • The uv.lock file that pins the exact versions of all dependencies was created.
  • A virtual env was created in .venv.
  • The dependencies were installed.
  • An editable install of my_hello_project was created (see uv pip freeze).
  • The tests were run.

Running the Project from the IDE

Now let's get our project running smoothly from within the IDE! Here are my step-by-step instructions on how to run the project from the IDE:

Important: Do not confuse my-hello-project (the name of the project) and my_hello_project (the name of the package)

  1. Open the main my-hello-project directory from within IntelliJ IDEA.
  2. Set up a Python SDK (Screenshot 1):
    • Navigate to File > Project Structure > Project Settings > SDKs.
    • Click the + button and select Add Python SDK from Disk.
    • In the dialog, select the following values:
      • Environment: Select Existing
      • Type: uv
      • Path to uv: /path/to/your/uv
      • Uv venv use: /path/to/python3/in/your/.venv/directory
    • Remember the name of the SDK you have just created.
  3. Set the SDK for the project (Screenshot 2):
    • Navigate to File > Project Structure > Project Settings > Project
    • Select the SDK you have just created in the SDK dropdown.
  4. Set the SDK for the module (Screenshot 3):
    • Navigate to File > Project Structure > Modules > my_hello_project > Dependencies
    • Select the SDK you have just created in the Dependency dropdown.
  5. Create a new Run Configuration (Screenshots 4 and 5):
    • Navigate to Run > Edit Configurations
    • Click the + button and select Python
    • Ensure the following values are set:
      • Use SDK of Module: my-hello-project
      • module: my_hello_project
    • Add a "Before Launch" task:
      • Click "Modify Options"
      • Choose "Add before launch task"
      • Choose "Run External tool" and click +:
      • Choose the following values and close the dialog:
        • Name: uv sync
        • Program: uv
        • Arguments: sync
        • Working directory: $ProjectFileDir$
      • Caveat: If your "Before Launch" task is not shown in the Run Configuration, make sure to not only set the checkbox but also select the uv sync entry before clicking OK.
Screenshot 1: Adding the Python Interpreter
Screenshot 2: Set the SDK for the project
Screenshot 3: Set the SDK for the module
Screenshot 5: The External Tool Configuration
Screenshot 5: The Completed Run Configuration
Screenshot 6: The Test Run Configuration

Now you can use the Run Configuration to run the project as expected. You should see some ASCII art and the Python version printed in the Run Output.

  _________________
| Running on 3.13.5 |
  =================
                 \
                  \
                    ^__^
                    (oo)\_______
                    (__)\       )\/\
                        ||----w |
                        ||     ||

Probably, you are wondering what the "Before Launch" task is for? uv sync ensures that the virtual environment is up to date and uses a Python version that matches the specifier in .python-version. Let's see that in action by switching to a different Python version (a pre-release in this case):

echo '3.14.0b4' > .python-version

and run the Program again through the Run Configuration and you are now on the pre-release version:

  ___________________
| Running on 3.14.0b4 |
  ===================
                        \
                         \
                          \
                           .--.
                          |o_o |
                          |:_/ |
                         //   \ \
                        (|     | )
                       /'\_   _/`\
                       \___)=(___/

uv as successfully upgraded the Python version used in the virtual env, even without us thinking a single second about any CLI commands. Isn't that great? :-)

Setting up a Run Configuration for tests is straight forward, just right-click the tests folder and select "Run 'Python tests in tests'" and you are set (Screenshot 6). I'd suggest then also adding a "Before Launch" task to run uv sync as described above. An even better approach is to the "Before Launch" task to the relevant Run/Debug Configuration Templates.

Epilogue: The "uv run" Run Configuration and Setting up an Entrypoint Script

You might have noticed that there's also a Run Configuration called "uv run." So, why did I opt for the lower level "Python" type with a "Before Launch" task to synchronize the virtual environment and execute the program? I faced two challenges:

  • I only could get it to work in "Debug" mode, but not in "Run" (see also this issue).
  • When upgrading to Python 3.14.0b4 it stopped working altogether.

But I guess that's just a matter of time and the issue will be resolved.

Finally, if your application is a CLI program, it's a good practice to set up an entrypoint script. This allows users to run your program with a simple command when installed on their system. For example, if you want your program to be callable by the name hello, set up the following:

cat << EOF >> pyproject.toml
[project.scripts]
hello = "my_hello_project.hello:run_hello"
EOF

The program can now be run with uv run hello. Or if you build and install it:

uv build
pipx install dist/*.whl
hello

Wenn du uns Kommentare oder Korrekturen mitteilen möchtest, kannst du unsere Engineers unter engineering-blog@cloudscale.ch erreichen.

Zurück zur Übersicht