Upgrading HomeAssistant Core in a Python VE

I’ve been able to upgrade from 3.9 to 3.11 with freebsd successfully. I did the requirements things, then I did it again without the requirements steps. The later is indeed superior. Much faster, not installing uneeded deps.

Here’s some fix I needed for FreeBSD:

After installing homeassistant:

pip3 install numpy
pip3 install git+https://github.com/rhasspy/webrtc-noise-gain.git|

I also have a problem with pyturbojpeg==1.7.1. I can install the updated version, but something requires this version that won’t install. That being said, it works so far. Note that my upgrade is small. I’ve started using ha like 3 days ago.

# update Home Assistant Core (HAC) venv on an Ubuntu 22.04 (jammy) system to use python3.12 in order to support "Home Assistant 2024.4" and newer HAC versions

# scenario:
# * Raspberry Pi 4B with Ubuntu 22.04 (jammy)
# * currently the HAC installation uses python3.11.9
# * HAC installation was previously (e.g. in 2022) set up as per
#   * https://www.home-assistant.io/installation/linux#install-home-assistant-core
#   * https://www.home-assistant.io/installation/raspberrypi#install-home-assistant-core
#   * notably, HAC venv is located at "/srv/homeassistant"
# * usual HAC update steps as per https://www.home-assistant.io/common-tasks/core/#update 
#   don't update beyond 2024.3.3 because HAC 2024.4+ requires python3.12 .

# if not already set up, add the deadsnakes PPA so that python3.12 is available for installation via apt
# see https://launchpad.net/~deadsnakes/+archive/ubuntu/ppa
sudo add-apt-repository ppa:deadsnakes/ppa
sudo apt update

# install all python3.12-relevant packages:
sudo apt install python3.12 python3.12-dev python3.12-venv

# sanity-check *system-wide* python3.12 installation:
which python3.12
# shall output "/usr/bin/python3.12"

python3.12 --version
# shall output "Python 3.12.x", e.g. "Python 3.12.4"

# stop homeassistant service
sudo systemctl stop homeassistant.service

# switch to Unix user "homeassistant"
sudo -u homeassistant -H -s

# now in the role of Unix user "homeassistant" 
# backup HAC venv directory
mkdir -p "${HOME}/backups/homeassistant/2024-07-01"
rsync -a /srv/homeassistant/ "${HOME}/backups/homeassistant/2024-07-01/homeassistant"

# see https://docs.python.org/3/library/venv.html
# while OUTSIDE of any venv, upgrade the HAC venv by executing
# "... -m venv --upgrade ..." with the desired python version,
# i.e. by explicitly using the "python3.12" executable:
python3.12 -m venv --upgrade /srv/homeassistant

# if this results in an error with message:
#   "Error: Unable to create directory '/srv/homeassistant'",
# then maybe the path "/srv/homeassistant" has a symlink along its path components?
# if so, then try the following command instead:
# python3.12 -m venv --upgrade "$(realpath /srv/homeassistant)"
#
# command shall exit without any output and with exit status 0.

# activate the upgraded venv
source /srv/homeassistant/bin/activate

# you are now as user "homeassistant" in an homeassistent (the application) venv.
# prompt should look similar to the following:
# (homeassistant) homeassistant@mymachine:/srv/homeassistant$

# ... ignore for a moment that the command "python --version" may still output e.g. "Python 3.11.9", not "Python 3.12.x"

pip3 install --upgrade homeassistant
# olala! something works:
# output:
#   Collecting homeassistant
#     Downloading homeassistant-2024.6.4-py3-none-any.whl.metadata (4.3 kB)
# ...
#
# collects packages, builds wheels, and installs collected packages.
# this can easily take over ten minutes on a Raspberry Pi 4B 
#
# in my case I got the following notice:
#   [notice] A new release of pip is available: 24.0 -> 24.1.1
#   [notice] To update, run: pip install --upgrade pip
# following suit:
pip install --upgrade pip

# continuing with https://www.home-assistant.io/common-tasks/core/#configuration-check :
hass --script check_config

# easily takes 30 minutes and more, as several packages may need to be compiled to the target architecture.
# outputs e.g.:
#   INFO:homeassistant.util.package:Attempting install of colorlog==6.8.2
#   Testing configuration at /home/homeassistant/.homeassistant
#   INFO:homeassistant.helpers.storage:Migrating core.entity_registry storage from 1.13 to 1.14
#   INFO:homeassistant.util.package:Attempting install of home-assistant-frontend==20240610.1
#   ...

# sanity check if the following command gives sensible output on your configuration:
hass --script check_config --info all

# we're done with the Home Assistant update/upgrade.

# time to start up Home Assistant as you usually do
# in my case the following steps were:
# leaving the venv:
deactivate

# leaving the shell as user "homassistant" to get back to my default user
exit

# now back in the role of my default user
# prepare to monitor the usual logs to see if everything starts up nicely, e.g. with
# journalctl -x -f
# Let's start Home Assistant now; in my case it goes like so:
sudo systemctl start homeassistant.service

# took 30 seconds or so until the first Home Assistant log entries appeared
# then the journalctl log shows that even more things get installed/updated, such as:
#   INFO (MainThread) [homeassistant.setup] Setup of domain logger took 0.23 seconds
#   ...
#   INFO (SyncWorker_1) [homeassistant.util.package] Attempting install of bar==4.5.6
# ... but the web interface is already reachable

This post is not for HAOS, but rather running HomeAssistant on a Ubuntu OS in a Pythone Virtual Environment.

If anyone is interested, this is the script I use to install and update both Python and HA Core (I called it updhass):

#!/bin/bash

LINE="START: $(date)"
echo "==${LINE}==" | sed "s/./=/g"
echo "= ${LINE} ="
echo "==${LINE}==" | sed "s/./=/g"

# Set this variable to the base directory of where your Python and HASS installations reside
DEF_BASE=/srv
DEF_CONFIG=~/.homeassistant
DEF_TEMP=Python_temp
F_PVER=""
F_HASS=""
NO_START_STOP=0

unset BASE CONFIG P_TEMP
# See if any command line parameters are provided
while getopts "?p:h:b:c:t:s" opt
do
        case "${opt}" in
                b) BASE=${OPTARG} ;;
                c) CONFIG=${OPTARG} ;;
                t) P_TEMP=${OPTARG} ;;
                p) F_PVER=${OPTARG} ;;
                h) F_HASS=${OPTARG} ;;
                s) NO_START_STOP=1 ;;
                \?)
                        echo "Usage: ${0} [-b Install_base] [-c Config_dir] [-t Python_Install_temp_dir] [-p Python_version] [-h HASS_version] [-s] [-?]"
                        echo "Where:"
                        echo -e "\tInstall_base is the base directory to install Python and HASS in (default ${DEF_BASE})"
                        echo -e "\tConfig_dir is the HASS config directory (default ${DEF_CONFIG})"
                        echo -e "\tPython_Install_temp_dir is the temp directory to build Python in (default ${DEF_BASE}/${DEF_TEMP})"
                        echo -e "\tPython_version is the Python version to use (i.e. 3.12.5)"
                        echo -e "\tHASS_version is the HASS version to use (i.e. 2024.8.2)"
                        echo "If -s is specified hass will not be restarted but new links will be created"
                        echo "When the HASS and Python version are already installed, the links will be recreated if they don't already exist"

                        exit 0
                ;;
        esac
done

[[ -z "${BASE}" ]] && BASE=${DEF_BASE}
# Make sure the BASE directory exists
if [[ ! -d "${BASE}" ]]
then
        mkdir -p ${BASE}
        if [[ $? != 0 ]]
        then
                echo "Problem creating base directory ${BASE}. Exiting..."
                exit 1
        fi
fi
# Make sure the BASE directory is writable
if [[ ! -w "${BASE}" ]]
then
        echo "Directory ${BASE} is write protected. Exiting..."
        exit 1
fi
if [[ -z "${P_TEMP}" ]]
then
        P_TEMP=${BASE}/${DEF_TEMP}
else
        # If P_TEMP does not start with a / prepend the BASE directory
        [[ $(echo ${P_TEMP} | cut -c1) -ne "/" ]] && P_TEMP=${BASE}/${P_TEMP}
fi

[[ -z "${CONFIG}" ]] && CONFIG=${DEF_CONFIG}
cd ${CONFIG}

# If we are in a venv, deactivate it
[[ $(type -t deactivate) == function ]] && deactivate
# Activate the latest HASS environment
[[ -d "${BASE}/hass/bin" ]] && source ${BASE}/hass/bin/activate

# Check if HASS is already installed?"
HASS_CVER=$(hass --version 2> /dev/null || echo "0000.0.0" )

# Retrieve the latest version of HASS from github
if [[ -z "${F_HASS}" ]]
then
        HASS_NVER=$(wget -q -O - https://github.com/home-assistant/core/releases/latest | grep 'href="/home-assistant/core/releases/tag' | sed 's/^.*href="//;s/".*//' | cut -d/ -f6)
else
        # Check if version from command line exists
        if wget -q -O /dev/null https://github.com/home-assistant/core/releases/tag/${F_HASS}
        then
                HASS_NVER=${F_HASS}
        else
                echo "HASS version ${F_HASS} is not found. Exiting..."
                exit 1
        fi
fi

# Do not upgrade to a .0 version
MINOR=$(echo "${HASS_NVER}" | cut -d. -f3)
echo "If this is a .0 version, skip the update; unless the version came from the command line"
if [[ ${MINOR} == 0 && -z "${F_HASS}" ]]
then
        echo "Not installing version ${HASS_NVER}"
        exit 1
fi

echo "Check and update Python if necessary"
[[ ! -d "${P_TEMP}" ]] && mkdir ${P_TEMP}
cd ${P_TEMP}

if [[ -z "${F_PVER}" ]]
then
        PFILE=$(wget -q https://python.org/downloads -O - --compression=gzip | grep "Download the latest .*tar.xz" | cut -d\" -f2 | sed "s/\.tar\.[^\.]\+$/.tgz/")
        N_PVER=$(basename  ${PFILE} .tgz | cut -d- -f2)
else
        N_PVER=${F_PVER}
        PFILE=https://www.python.org/ftp/python/${N_PVER}/Python-${N_PVER}.tgz
fi

PVER_PATH=Python-${N_PVER}
PPATH=${BASE}/${PVER_PATH}

if [[ -d "${PPATH}"/bin ]]
then
        echo "Python ${N_PVER} is already installed..."
else
        echo "Collecting and extracting tarbal for Python ${N_PVER}..."
        wget -q ${PFILE} -O - | tar zxf -
        if [[ $? == 0 && -d ${P_TEMP}/Python-${N_PVER} ]]
        then
                cd ${P_TEMP}/${PVER_PATH}
                echo "Compiling and installing Python ${N_PVER}..."
                ./configure --prefix=${PPATH} --enable-optimizations && make -j 4 && make install
                if [[ $? -ne 0 ]]
                then
                        echo "Something went wrong with building Python ${N_PVER}..."
                else
                        echo "Create virtual environment for Python ${N_PVER} in ${PPATH}..."
                        export PATH=${PPATH}/bin:${PATH}
                        python3 -m venv ${PPATH}/venv
                fi

                echo "Cleaning up the sourcefiles..."
                cd ${P_TEMP}
                rm -rf ${PVER_PATH}
        else
                echo "Something went wrong while collecting and extracting source file ${PFILE}"
        fi

        echo "Done."
fi

cd ${CONFIG}

# Check the current version of Python
C_PVER=$(python3 --version | sed "s/ /-/g")
# Grab the latest installed Python version or the version from the command line
if [[ -z "${F_PVER}" ]]
then
        PVER=$(ls -d ${BASE}/Python-*/venv | tail -1 | rev | cut -d/ -f2 | rev)
else
        PVER="Python-${F_PVER}"
        if [[ ! -d ${BASE}/${PVER}/venv/bin ]]
        then
                echo "Python version ${PVER} is not available. Exiting..."
                exit 1
        fi
fi

DDIR="${BASE}/${PVER}/HASS-${HASS_NVER}"
SL=${BASE}/hass-${HASS_NVER}_${PVER}

# Run the update if there is a new version of Python or a new version of HASS
DORELINK=0
echo "Is Python/HASS combo already installed?"
# if [[ "${HASS_CVER}" != "${HASS_NVER}" || "${C_PVER}" != "${PVER}" ]]
if [[ -x "${DDIR}/bin/hass" ]]
then
        # Yes, do we need to relink the files?
        ls -ld ${BASE}/hass | grep -q ${SL} || DORELINK=1
else
        # No, install HASS
        mkdir -p ${DDIR}
        # If we are in a venv, deactivate it
        [[ $(type -t deactivate) == function ]] && deactivate

        # Activate the generic venv for the latest Python version (as created by the updPython script)
        source ${BASE}/${PVER}/venv/bin/activate

        # Create a virtual environment for the latest Python/HASS combo
        python3 -m venv ${DDIR}
        # Deactivate the generic venv for the latest Python version
        deactivate
        # Activate the venv for the latest Python/HASS combo
        source ${DDIR}/bin/activate
        # ensure we have the latest pip
        pip3 install --upgrade pip

        # Force installation of the latest HASS version
        REQ_FILE=~/hass_requirements.txt
        sed -i.$(date +'%Y%m%d%H%M%S') "s/homeassistant==.*/homeassistant==${HASS_NVER}/" ${REQ_FILE}
        pip3 install -r ${REQ_FILE}

        # deactivate the venv for the latest Python/HASS combo
        deactivate
        DORELINK=1
fi

if [[ "${DORELINK}" == 1 ]]
then
        [[ ${NO_START_STOP} == 0 ]] && echo "Stopping old version of HASS"
        [[ ${NO_START_STOP} == 0 ]] && sudo systemctl stop home-assistant@homeassistant
        # Recreate links to the latest Python/HASS combo
        echo "Creating links for Python/HASS combo"
        rm -f ${BASE}/hass ${SL}
        ln -s ${DDIR} ${SL}
        ln -s ${SL} ${BASE}/hass
        [[ ${NO_START_STOP} == 0 ]] && echo "Starting new version of HASS"
        [[ ${NO_START_STOP} == 0 ]] && sudo systemctl start home-assistant@homeassistant
fi

LINE="END: $(date)"
echo "==${LINE}==" | sed "s/./=/g"
echo "= ${LINE} ="
echo "==${LINE}==" | sed "s/./=/g"

And this is my ~/hass_requirements.txt file (adjust it as necessary). The version of homeassistant is changed when the script is run:

wheel
mysqlclient==2.1.1
click==8.0.4
zha-quirks
moonraker-api
psutil-home-assistant
pyturbojpeg
homeassistant==2024.9.1
homeassistant-cli
numpy

So what this script does is the following:

  • it uses /srv as the base install directory. Update this to what works for you
  • check if a new version of Python exists
    • if so, install it in /srv/Python-x.yy.z
    • create a venv for this version in /srv/Python-x.yy.z/venv
  • check if a new version of HA Core exists
    • if so, create a venv with the latest version of Python in /srv/Python-x.yy.z/HASS-aaaa.b.c
    • activate this venv and use pip3 to install homeassistant
    • shutdown the exisiting version of HA Core (in this script, I use systemctl but you can change that anyway you handle HA Core startup and shutdown)
    • backup the current /srv/hass symbolic link to /srv/hass-aaaa.b.c_Python-x.yy.z
    • create a symbolic link to from the new install directory to /srv/hass
    • start the new installation of HA Core

These are the commandline options:

$ ./updhass -?
===========================================
= START: Sat Sep  7 07:28:17 AM CEST 2024 =
===========================================
Usage: ./updhass [-b Install_base] [-c Config_dir] [-t Python_Install_temp_dir] [-p Python_version] [-h HASS_version] [-s] [-?]
Where:
        Install_base is the base directory to install Python and HASS in (default /srv)
        Config_dir is the HASS config directory (default /home/homeassistant/.homeassistant)
        Python_Install_temp_dir is the temp directory to build Python in (default /srv/Python_temp)
        Python_version is the Python version to use (i.e. 3.12.5)
        HASS_version is the HASS version to use (i.e. 2024.8.2)
If -s is specified hass will not be restarted but new links will be created
When the HASS and Python version are already installed, the links will be recreated if they don't already exist

With -p and -h you can force a specific Python or HA version. Without any options, it will simple install the latest versions of Python and HA Core if necessary.

This script assumes, you have installed all other prerequisites for running HA Core (see Install Home Assistant Core)

This script ensures, I ALWAYS have a fresh install of HA Core and its requirements, but it always uses the same config directory. I am running HA Core under Rocky Linux 9 but this script should also work under Debian/Raspbian and Ubuntu

Hello,

I was on Ubuntu 24.04 LTS with Python 3.12, using Home Assistant 2024.11.

As Home Assistant 2024.12 now supports Python 3.13 and 2025.2 will require it, which doesn’t natively ship with Ubuntu 24.04, I upgraded using the following steps.

The key ideas were:

  • Use uv for installing Python 3.13, because uv can install it in a way that doesn’t interfere with the system’s Python at all.
  • Keep the upgrade steps close to the official installation docs (Linux - Home Assistant).
sudo systemctl stop home-assistant@homeassistant

cd /srv
sudo mv homeassistant homeassistant-old-3.12
sudo mkdir homeassistant
sudo chown homeassistant:homeassistant homeassistant

# Now work as user `homeassistant`.
sudo -u homeassistant -H -s

# If `uv` is not yet installed:
cd ~
curl -LsSf https://astral.sh/uv/install.sh | sh
source $HOME/.local/bin/env

# Install Python 3.13:
uv python install 3.13

# Create the virtual environment and install `homeassistant`:
cd /srv/homeassistant
uv venv . --python 3.13
source bin/activate
uv pip install homeassistant==2024.12.5

# It takes a while before your HA system becomes available in the browser.
# Check for log output, test your system in the browser, then quit with CTRL+C.
hass
exit

sudo systemctl start home-assistant@homeassistant

This worked very well for me, but note that my Home Assistant install doesn’t include any custom Python packages or other non-standard extras.

2 Likes

thanks for posting the steps, but the above isn’t correct to my best knowledge. HA 2025.2 will require Python 3.13, 2024.12.x runs with Python 3.12 in a core venv and only tells you on startup that it is deprecated, no need to rush to 3.13:
2025-01-02 15:40:37.893 WARNING (MainThread) [homeassistant.bootstrap] Support for the running Python version 3.12.7 is deprecated and will be removed in Home Assistant 2025.2; Please upgrade Python to 3.13

I’m sorry, you’re right, thanks for pointing this out. I’ve edited my post above to reflect this.

Tried upgrading hass to python3.13 and found the setup script doesn’t work.
Same script worked fine on 3.12 with december Core version: 2025.2.0.dev0

Deleted the old venv folder with 3.12 and created a new one with 3.13.
It appears to have sensed Python3.13 is installed and used it.

homeassistant@Alderaan:~/core$ script/setup
Installing development dependencies...
Using Python 3.13.0 environment at: venv
Resolved 1 package in 312ms
Audited 1 package in 0.29ms
Using Python 3.13.0 environment at: venv
Resolved 2 packages in 125ms
Audited 2 packages in 0.06ms
Using Python 3.13.0 environment at: venv
Resolved 94 packages in 1.47s
Audited 94 packages in 0.14ms
Traceback (most recent call last):
  File "/home/homeassistant/core/venv/bin/pre-commit", line 5, in <module>
    from pre_commit.main import main
  File "/home/homeassistant/core/venv/lib/python3.13/site-packages/pre_commit/main.py", line 14, in <module>
    from pre_commit.commands.clean import clean
  File "/home/homeassistant/core/venv/lib/python3.13/site-packages/pre_commit/commands/clean.py", line 6, in <module>
    from pre_commit.store import Store
  File "/home/homeassistant/core/venv/lib/python3.13/site-packages/pre_commit/store.py", line 6, in <module>
    import sqlite3
  File "/usr/local/lib/python3.13/sqlite3/__init__.py", line 57, in <module>
    from sqlite3.dbapi2 import *
  File "/usr/local/lib/python3.13/sqlite3/dbapi2.py", line 27, in <module>
    from _sqlite3 import *
ModuleNotFoundError: No module named '_sqlite3'

Any ideas what to do about it?

Found another clue when I upgraded .venv folder to Python3.13 for the package my component uses.
Same error, this time from pytest coverage:

 File "/mnt/b/HomeAssistant/sonnen_api_v2/.venv/lib/python3.13/site-packages/pytest_cov/plugin.py", line 9, in <module>
    import coverage
  File "/mnt/b/HomeAssistant/sonnen_api_v2/.venv/lib/python3.13/site-packages/coverage/__init__.py", line 24, in <module>
    from coverage.control import (
    ...<2 lines>...
    )
  File "/mnt/b/HomeAssistant/sonnen_api_v2/.venv/lib/python3.13/site-packages/coverage/control.py", line 27, in <module>
    from coverage.collector import Collector
  File "/mnt/b/HomeAssistant/sonnen_api_v2/.venv/lib/python3.13/site-packages/coverage/collector.py", line 20, in <module>
    from coverage.data import CoverageData
  File "/mnt/b/HomeAssistant/sonnen_api_v2/.venv/lib/python3.13/site-packages/coverage/data.py", line 26, in <module>
    from coverage.sqldata import CoverageData
  File "/mnt/b/HomeAssistant/sonnen_api_v2/.venv/lib/python3.13/site-packages/coverage/sqldata.py", line 16, in <module>
    import sqlite3
  File "/usr/local/lib/python3.13/sqlite3/__init__.py", line 57, in <module>
    from sqlite3.dbapi2 import *
  File "/usr/local/lib/python3.13/sqlite3/dbapi2.py", line 27, in <module>
    from _sqlite3 import *
ModuleNotFoundError: No module named '_sqlite3'

I found this article that lead me to a solution:
missing-sqlite3-after-python3-compile-on-linux

I had installed sqlite3 dev using:
sudo apt instal libsqlite3-dev

The default ./configure shows this for sqlite3:

checking for sqlite3 >= 3.15.2... yes
checking for sqlite3.h... yes
checking for sqlite3_bind_double in -lsqlite3... yes
checking for sqlite3_column_decltype in -lsqlite3... yes
checking for sqlite3_column_double in -lsqlite3... yes
checking for sqlite3_complete in -lsqlite3... yes
checking for sqlite3_progress_handler in -lsqlite3... yes
checking for sqlite3_result_double in -lsqlite3... yes
checking for sqlite3_set_authorizer in -lsqlite3... yes
checking for sqlite3_trace_v2 in -lsqlite3... yes
checking for sqlite3_value_double in -lsqlite3... yes
checking for sqlite3_load_extension in -lsqlite3... yes
checking for sqlite3_serialize in -lsqlite3... yes
checking for **--enable-loadable-sqlite-extensions... no**

Changed the configure command to:

sudo ./configure --enable-optimizations **--enable-loadable-sqlite-extensions  --with-pydebug**

checking for --enable-loadable-sqlite-extensions... yes

which fixed the issue with pytest.
Virtual environment did not have to be recreated, it just worked with rebuilt Python3.13.

Core script/setup also worked after Python rebuild.

Thank you! I couldn’t get things to work via the original instructions, but your steps involving the use of “uv” did the trick!

Worked great for me, nice and simple, just had to:

uv pip install mysqlclient

after installing HA in the venv, before restarting.

Carsten,

Thanks for shining a light on the uv method for upgrading …

In your post you say:

My directory structure is different (I am not using the /srv directory).

Is the “homeassistant” directory, the one that has requirements.txt?

In your case is the configuration directory ( the one that contains *.yaml, .storage, …etc) NOT under the “homeassistant” directory?

Thanks in advance.

Not sure if it’s worth the effort to spend too much time on core, given it is likely to be phased out.

According to the comments in the link, Core will NOT be phased out.

It will be documented in the developer section, rather than the end user section, and will continue to exist.

Without support.

I (I am only speaking for myself) have no issues with that.
I have 3 installations.

The original one is Core.
One is HA Green
One is HassOS on Proxmox.

If they plan on making Core unsupported that is OK. But they should provide some details of moving from “A” to “B” with respect to getting a new install which is say HassOS using a backup from Core.

Not to mention things that haven serial interfaces, or special sound drivers.

I think Core has been without support for a while now.
Hence why I created this post on how to upgrade it.

Core has pretty much been supported by the community for some time now.

Carsten,

Thanks to your post, I was able to update my Core to the latest version.

I had Core installed as my regular user, so there is no need to sudo to the homassistant user or anything like that.
It works very well.

The only question I have now is how to upgrade this installation, like I used to do with pip install --upgrade .... The uv command has no option for update at all. But perhaps that is not needed, since we can do the same thing we did and mv the directory, create a new one, instantiate a venv, then install HA from scratch.

One more thing to add to your list of commands is this step:

$HA_DIR/bin/hass -c $CONF_DIR --script check_config

Before starting hass. That will display any errors in the config YAML files so they can be addressed before hass is run.

andy2

I had to do something similar …

In my case, the recorder uses MariaDB, and my connection string to the database is like this:

mysql+pymysql://dbuser:[email protected]/dbname?charset=utf8mb4

So I had to do

uv pip install pymysql

After I installed Home Assistant