Python is a interpreted language, so the python code are just text
files with the
.py extension. For simple scripts it's really easy to
have your files located, but when you starts to use dependencies and
different projects with different requirements the thing starts to get
The Python interpreter uses a list of paths to try to locate python
modules, for example this is what you can get in a modern GNU/Linux
distribution by default:
Python 3.11.7 (main, Dec 15 2023, 10:49:17) [GCC] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import sys
These are the default paths where the python modules are installed. If
you install any python module using your linux packaging tool, the
python code will be placed inside the
So system installed python modules can be located in:
/usr/lib/python3.11/site-packages for modules that are
architecture independent (pure python, all
/usr/lib64/python3.11/site-packages for modules that depends on
the arquitecture, that's something that uses low level libraries
and needs to build so there are some
When you need a new python dependency you can try to install from your
GNU/Linux distribution using the default package manager like
apt, and those python files will be placed in the
system paths that you can see above.
But distributions doesn't pack all the python modules and even if they
do, you can require an specific version that's different from the one
packaged in your favourite distribution, so in python it's common to
install dependencies from the Python Package Index (PyPI).
Python has a tool to install and manage Python packages that looks for
desired python modules in PyPI.
You can install new dependencies with
pip just like:
And that command looks for the
django python module in the PyPI,
downloads and install it, in your user
$HOME/.local/lib/python3.11/site-packages folder if you
--user, or in a global system path like
/usr/lib if you run pip as root.
But the usage of
pip directly in the system is something not
recommended today, and even it's disabled in some
distributions, like openSUSE Tumbleweed.
[danigm@localhost ~] $ pip install django
× This environment is externally managed
╰─> To install Python packages system-wide, try
zypper install python311-xyz, where xyz is the package
you are trying to install.
If you wish to install a non-rpm packaged Python package,
create a virtual environment using python3.11 -m venv path/to/venv.
Then use path/to/venv/bin/python and path/to/venv/bin/pip.
If you wish to install a non-rpm packaged Python application,
it may be easiest to use `pipx install xyz`, which will manage a
virtual environment for you. Install pipx via `zypper install python311-pipx` .
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.
Following the current recommendation, the correct way of installing
third party python modules is to use
virtualenvs are just specific folders where you install your
python modules and some scripts that make's easy to use it in
combination with your system libraries so you don't need to modify the
So if you've a custom project and want to install python modules you
can create your own virtualenv and use pip to install dependencies
[danigm@localhost tmp] $ python3 -m venv myenv
[danigm@localhost tmp] $ . ./myenv/bin/activate
(myenv) [danigm@localhost tmp] $ pip install django
Successfully installed asgiref-3.7.2 django-5.0.1 sqlparse-0.4.4
So all dependencies are installed in my new virtualenv folder and if I
use the python from the virtualenv it's using those paths, so all the
modules installed there are usable inside that virtualenv:
(myenv) [danigm@localhost tmp] $ ls myenv/lib/python3.11/site-packages/django/
apps contrib db forms __init__.py middleware shortcuts.py templatetags urls views
conf core dispatch http __main__.py __pycache__ template test utils
(myenv) [danigm@localhost tmp] $ python3 -c "import django; print(django.__version__)"
(myenv) [danigm@localhost tmp] $ deactivate
With virtualenvs you can have multiple python projects, with different
dependencies, isolated, so you use different dependencies when you
activate your desired virtualenv:
$ . ./myenv/bin/activate
High level tools to handle virtualenvs
The venv module is a default Python module and as you can see
above, it's really simple to use, but there are some tools that
provides some tooling around it, to make it easy for you, so usually
you don't need to use
For final python tools, that you are not going to use as dependencies
in your python code, the recommended tool to use is pipx.
The tool creates virtualenv automatically and links the binaries so
you don't need to worry about anything, just use as a way to install
third party python applications and update/uninstall using it. The
pipx won't mess your system libraries and each installation will use
a different virtualenv, so even tools with incompatible dependencies
will work nicely together in the same system.
Libraries, for Python developers
In the case of Python developers, when you need to manage dependencies
for your project, there are a lot of nice high level tools for
These tools provides different ways of managing dependencies, but all
of them relies in the use of
venv, creating the virtualenv in
different locations and providing tools to enable/disable and manage
dependencies inside those virtualenvs.
poetry creates virtualenvs by default inside the
.cache folder, in my case I can find all poetry created virtualenvs
Most of these tools add other utilities on top of the dependency
management. Just for installing python modules easily you can always
pip modules, but for more complex projects
it's worth to investigate high level tools, because it'll make easy to
manage your project dependencies and virtualenvs.
There are a lot of python code inside any modern Linux distribution
and if you're a python developer it's possible to have a lot of python
code. Make sure to know the source of your modules and do not mix
different environments to avoid future headaches.
As a final trick, if you don't know where's the actual code of some
python module in your running python script, you can always ask:
>>> import django
This could be even more complicated if you start to use containers
and different python versions, so keep you dependencies clean and up
to date and make sue that you know where is your Python code.
There are comments.