Making your Python package installable#
Caution
Projects with a pyproject.toml are currently the default for pure Python projects.
In ROS2, currently we fully rely on setup.py approach using setuptools therefore that’s what I discuss herein.
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
|-- minimalist_package
| |-- __init__.py
| |-- _minimalist_class.py
| |-- minimalist_async
| | |-- __init__.py
| | |-- _unlikely_to_return.py
| | |-- async_await_example.py
| | `-- async_callback_example.py
| `-- minimalist_script.py
|-- setup.py
`-- test
`-- test_minimalist_class.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, in the following directory, ~/ros2_tutorials_preamble/python/minimalist_package we create the file below.
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