Note

This section is optional, the ROS2 tutorial starts at ROS2 Installation.

Making your Python package installable

Warning

There is some movement towards having Python deployable packages configurable with pyproject.toml as a default. However, in ROS2 and many other frameworks, the setup.py approach using setuptools is ingrained. So, we’ll do that for these tutorials but it doesn’t necessarily mean it’s the best approach.

Use a venv

We already know that it is a good practice to When you want to isolate your environment, use venv. So, let’s turn that into a reflex and do so for this whole section.

cd ~
source ros2tutorial_venv/bin/activate

The setup.py

In this step, we’ll work on this.

python/minimalist_package/
  setup.py

Has Python Packaging ever looked daunting to you? Of course not, but let’s go through a quick overview of how we can get this done.

First, we create a setup.py at ~/ros2_tutorials_preamble/python/minimalist_package with the following contents

setup.py

from setuptools import setup, find_packages

package_name = 'minimalist_package'

setup(
    name=package_name,
    version='23.6.0',
    packages=find_packages(exclude=['test']),
    install_requires=['setuptools'],
    zip_safe=True,
    maintainer='Murilo M. Marinho',
    maintainer_email='murilomarinho@ieee.org',
    description='A minimalist package',
    license='MIT',
    entry_points={
        'console_scripts': [
            'minimalist_script = minimalist_package.minimalist_script:main',
            'async_await_example = minimalist_package.minimalist_async.async_await_example:main',
            'async_callback_example = minimalist_package.minimalist_async.async_callback_example:main'
        ],
    },
)

Note

By no coincidence, the setup.py is a Python file. We use Python to interpret it, meaning that we can process information using Python to define the arguments for the setup() function.

All arguments defined above are quite self-explanatory and are passed to the setup() function available at the setuptools module built into Python.

The probably most unusual part of it is the entry_points dictionary. In the key console_scripts, we can list up scripts in the package that can be used as console programs after the package is installed. Indeed, setuptools is rich, has a castle, and can do magic.

Installing wheel

Warning

In the current version of Python, if you do not install wheel as described herein, the following warning will be output.

DEPRECATION: minimalist-package is being installed using the legacy 'setup.py install' method because it does not have a 'pyproject.toml'
and the 'wheel' package is not installed. pip 23.1 will enforce this behaviour change. A possible replacement is to enable the '--use-pep517'
option. Discussion can be found at https://github.com/pypa/pip/issues/8559

To install the package in the recommended way in this tutorial, we need wheel. While using the venv, we install it

python3 -m pip install wheel

Installing the Python package

We first go to the folder containing our project folder and we build and install the project folder within it using pip as follows

cd ~/ros2_tutorials_preamble/python
python3 -m pip install ./minimalist_package

which results in

Processing ./minimalist_package
  Preparing metadata (setup.py) ... done
Requirement already satisfied: setuptools in ~ros2tutorial_venv/lib/python3.10/site-packages (from minimalist-package==23.6.0) (65.6.3)
Building wheels for collected packages: minimalist-package
  Building wheel for minimalist-package (setup.py) ... done
  Created wheel for minimalist-package: filename=minimalist_package-23.6.0-py3-none-any.whl size=8608 sha256=929446a2fa81fc99fc5dec239a9f3e4439bc8fa8fe49cc4deb987d6f31b3d8b9
  Stored in directory: /private/var/folders/4k/20khytt17blf21lptscczbl00000gn/T/pip-ephem-wheel-cache-j3a0f5xy/wheels/00/16/ef/863b898c6ea4d32d47a24fda31f80cbc9cb1063742032b7d49
Successfully built minimalist-package
Installing collected packages: minimalist-package
Successfully installed minimalist-package-23.6.0

Done!

Running the newly available scripts

After installing, we have access to the scripts (and packages). For instance, we can do

minimalist_script

which will return the friendly

Howdy!
Howdy!
Howdy!

The other two scripts are also available, for instance, we can do

async_await_example

which will return something similar to

Awaiting results...
task1 retry needed (roll = 0.1534174185325745 > 0.1).
task2 retry needed (roll = 0.35338687437350913 > 0.1).
task1 Done.
task2 retry needed (roll = 0.3877920607121429 > 0.1).
The result of task=task1 was 0.07646509818952207.
task2 retry needed (roll = 0.7010015915930288 > 0.1).
task2 retry needed (roll = 0.8907576123834621 > 0.1).
task2 retry needed (roll = 0.4233577578392548 > 0.1).
task2 retry needed (roll = 0.7512028176843422 > 0.1).
task2 retry needed (roll = 0.33501957024540663 > 0.1).
task2 Done.
The result of task=task2 was 0.09239734738421612.

Importing things from the installed package

We first run an interactive session with

python3

we can then interact with it as any other installed package

>>> from minimalist_package import MinimalistClass
>>> mc = MinimalistClass()
>>> print(mc.get_private_attribute())
20.0

Hooray!

Uninstalling packages

Given that we installed it using pip, removing it is also a breeze. We do

python3 -m pip uninstall minimalist_package

which will return something similar to

Found existing installation: minimalist-package 23.6.0
Uninstalling minimalist-package-23.6.0:
  Would remove:
    /home/murilo/ros2tutorial_venv/bin/async_await_example
    /home/murilo/ros2tutorial_venv/bin/async_callback_example
    /home/murilo/ros2tutorial_venv/bin/minimalist_script
    /home/murilo/ros2tutorial_venv/lib/python3.10/site-packages/minimalist_package-23.6.0.dist-info/*
    /home/murilo/ros2tutorial_venv/lib/python3.10/site-packages/minimalist_package/*
Proceed (Y/n)?

and just press ENTER, resulting in the package being uninstalled

Successfully uninstalled minimalist-package-23.6.0