I have a utility written in Python that I used to use and need to use it again.
It’s done as a package I install and an executable script with shebang that will be imported and called the main function.
The usage is just like any other utility as in other languages. Just call the executable that wraps the module’s main call.
But after updating Ubuntu from 22.04 to 24.04, when I try to install the packages system-wide using pip, I get the following message defined by the PEP-668:
$ /usr/bin/python3 -m pip install -U --user -e ./
error: externally-managed-environment
× This environment is externally managed
╰─> To install Python packages system-wide, try apt install
python3-xyz, where xyz is the package you are trying to
install.
If you wish to install a non-Debian-packaged Python package,
create a virtual environment using python3 -m venv path/to/venv.
Then use path/to/venv/bin/python and path/to/venv/bin/pip. Make
sure you have python3-full installed.
If you wish to install a non-Debian packaged Python application,
it may be easiest to use pipx install xyz, which will manage a
virtual environment for you. Make sure you have pipx installed.
See /usr/share/doc/python3.12/README.venv for more information.
note: If you believe this is a mistake, please contact your Python installation or OS distribution provider. You can override this, at the risk of breaking your Python installation or OS, by passing --break-system-packages.
hint: See PEP 668 for the detailed specification.
I managed to install the dependencies using the APT package equivalents (python-xyz), but for installing my own package this doesn’t work.
I am not used to venvs, but they require extra steps before using it like activating the environment etc that I can’t conciliate with a system-wide available script. I can choose the Python binary to run the script in the shebang, but that’s all I think I can do.
So, after PEP-668, how to create an application to run system-wide, that can be called from the shell or a .desktop
XDG application entry without writing a local Debian (or any other OS) package?
The application in question is open source and can be found here: https://github.com/AllanDaemon/uchoose
Using pip with --break-system-packages
like above, alongside with other hacks, did work for me. But it seems too hackish. Maybe it’s the ideal solution for this kind of case, but I get the feeling this isn’t ideal.
/usr/bin/python3 -m pip install --break-system-packages -U --user ./
2
Answers
Creating a system-wide install of Python using
venv
is going to be the cleanest way of doing this.Using a location such as
/opt/venv
that is owned by an admin user is a good idea. Administering thevenv
as a dedicated user has the advantage of not running module installs as root.Then scripts you want to use this
venv
can either have the location hardcoded in the shebang line e.g.Or my preference would be to modify user’s environment with
/opt/venv/bin
at the start of$PATH
so that you can use the more flexible:Or if you are installing these scripts from a package, then using Python package management to create executable scripts is the best idea and avoid the need for a shebang line in your scripts.
The steps for the creation of the
venv
might look like:This can works with you
or you can use this if your linux mirrors didn’t get it