Packages

Packages#

This section covers questions related to packages. In fact packages - just a folder that contains Python sources. In a narrower context it’s a way to distribute your solutions, this page understands package in such context.

Building#

A folder containing sources must be transformed into a special format suitable for distribution. This section covers the basics of building packages - converting them into a form convenient for distribution.

To build a package, you need to:


All you need is a src folder containing the source code of the package and a pyproject.toml configuration file that specifies how the project should be built.

tree packages_files/building
packages_files/building
├── pyproject.toml
└── src

1 directory, 1 file

Here is content of the pyproject.toml that is used for example.

cat packages_files/building/pyproject.toml
[project]
name = "example_package_FEDOR_KOBAK"
version = "0.0.4"
authors = [
  { name="Fedor Kobak", email="kobfedsur@gmail.com" },
]
description = "A small example package"

The simplest building tool is the build package. The following cell applies it to the project template created earlier.

python3 -m build packages_files/building --outdir /tmp/build_out &> /dev/null

Here is the result of the construction:

tree /tmp/build_out
/tmp/build_out
├── example_package_FEDOR_KOBAK-0.0.4-py3-none-any.whl
└── example_package_fedor_kobak-0.0.4.tar.gz

0 directories, 2 files

The result includes .tar.gz and .whl files, both of which are options for distributing Python packages.

There are some service files that were generated during the build of the following cell, remove those files.

rm -r packages_files/building/src/example_package_FEDOR_KOBAK.egg-info

Installation#

Install packages with pip package. So typical installation looks like pip3 install <target to be installed>.

The most important tool for handling package installations in Python is pip. Check the specific page on pip for more details.


Consider installing the pre-prepared package. The following cell creates a new virtual environment, activates it, and installs the pre-prepared file.

python3 -m venv /tmp/test_venv
source /tmp/test_venv/bin/activate
pip3 install packages_files/example_package_fedor_kobak-0.0.4.tar.gz
Processing ./packages_files/example_package_fedor_kobak-0.0.4.tar.gz
  Installing build dependencies ... ?25ldone
?25h  Getting requirements to build wheel ... ?25ldone
?25h  Preparing metadata (pyproject.toml) ... ?25ldone
?25hBuilding wheels for collected packages: example_package_FEDOR_KOBAK
  Building wheel for example_package_FEDOR_KOBAK (pyproject.toml) ... ?25ldone
?25h  Created wheel for example_package_FEDOR_KOBAK: filename=example_package_FEDOR_KOBAK-0.0.4-py3-none-any.whl size=1630 sha256=1cc073b7d6d1ac4732fb50310b43df8cedbbbf50527091bc611c0be425b9f28f
  Stored in directory: /home/f.kobak@maxbit.local/.cache/pip/wheels/2f/75/0c/4013918bb2a37cc2500176bad7b2549e598dc15572f73c419e
Successfully built example_package_FEDOR_KOBAK
Installing collected packages: example_package_FEDOR_KOBAK
Successfully installed example_package_FEDOR_KOBAK-0.0.4

The installed package appears in the lib/<python version>/site-packages folder of the environment you’re working with:

tree /tmp/test_venv/lib/python3.10/site-packages/example_package
/tmp/test_venv/lib/python3.10/site-packages/example_package
├── example.py
├── __init__.py
└── __pycache__
    ├── example.cpython-310.pyc
    └── __init__.cpython-310.pyc

1 directory, 4 files

Now confirm that the installed project really works.

python3 -c "import example_package"
deactivate
I'm installed package!

Importing the installed package unlocks the message embedded in it.

Uploading#

For uploading can be used twine library. It allows to push arbitrary package to the selected python index (PyPI is one of them).


To play with uploading Python packages, a Python index is required. To prevent creating tons of packages available on the internet, you can set up a self-hosted Python index using devpi. The following cell creates and configures such a setup:

docker run -itd --rm \
    --network host --name devpi-server python:3.12 \
    bash -c "pip3 install devpi && devpi-init && devpi-server" 
sleep 10 
docker exec devpi-server bash -c "
    while ! devpi use http://localhost:3141 &> /dev/null; do sleep 1; done
    devpi user -c fedor password=hello
    devpi login fedor --password hello
    devpi index -c prod
    devpi use fedor/prod
    mkdir temp
    pip3 download setuptools wheel -d ./temp
    devpi upload --from-dir ./temp
" &> /dev/null
c6042d007e38c1f491427038157a0f9ebc40cd9ca0f96ebef013ca6d17afb0f4

Now creating separate environment and installation of the twine library.

python3 -m venv /tmp/uploading_venv
source /tmp/uploading_venv/bin/activate
pip3 install twine &> /dev/null

The next cell shows how to add a package to the index you just created.

twine upload \
    --repository-url http://localhost:3141/fedor/prod/ \
    ./packages_files/example_package_fedor_kobak-0.0.4.tar.gz \
    --password hello \
    --username fedor
Uploading distributions to http://localhost:3141/fedor/prod/
Uploading example_package_fedor_kobak-0.0.4.tar.gz
100% ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 3.7/3.7 kB00:00?
?25h

Let’s see if everything works fine as a result by installing the created package and inwoking it.

pip3 install -i http://localhost:3141/fedor/prod example_package-FEDOR-KOBAK
python3 -c "import example_package"
Looking in indexes: http://localhost:3141/fedor/prod
Collecting example_package-FEDOR-KOBAK
  Using cached example_package_FEDOR_KOBAK-0.0.4-py3-none-any.whl
Installing collected packages: example_package-FEDOR-KOBAK
Successfully installed example_package-FEDOR-KOBAK-0.0.4
I'm installed package!

So we got massage I'm installing package that was embedded in it.

Finally don’t forget to clear everything was created in environment for this example.

docker stop devpi-server
deactivate
rm -r /tmp/uploading_venv/
devpi-server