Installing Python scripts and modules

Even if your_package only contains Python code, it still needs a catkin CMakeLists.txt to install executable scripts and to export modules so they can be imported in other ROS packages.


ROS executables are installed in a per-package directory, not the distributions’s global bin/ directory. They are accessible to rosrun and roslaunch, without cluttering up the shell’s $PATH, and their names only need to be unique within each package. There are only a few core ROS commands like rosrun and roslaunch that install in the global bin/ directory.

Standard ROS practice is to place all executable Python programs in a package subdirectory named nodes/ or scripts/. Their usage is the same, the two names distinguish ROS nodes from other executable Python scripts. To keep the user API clean, executable script names generally do not include a .py suffix. Your CMakeLists.txt should install all the scripts explictly using the special install function catkin_install_python. This will make sure that shebang lines are updated to use the specific Python version used at configure time:

catkin_install_python(PROGRAMS nodes/your_node scripts/another_script

Another good practice is to keep executable scripts very short, placing most of the code in a module which the script imports and then invokes:

#! /usr/bin/env python3
import your_package.main
if __name__ == '__main__':


Standard ROS practice is to place Python modules under the src/your_package subdirectory, making the top-level module name the same as your package. Python requires that directory to have an file, too.


With rosbuild, it was possible to place Python modules directly within src/. That violated Python setup conventions, and catkin does not allow it. If you need to define a module named your_package, place its code in src/your_package/ or import its public symbols there.

Catkin installs Python packages using a variant of the standard Python script. Assuming your modules use the standard ROS layout, it looks like this:


from setuptools import setup
from catkin_pkg.python_setup import generate_distutils_setup

# fetch values from package.xml
setup_args = generate_distutils_setup(
    package_dir={'': 'src'})


Note: As in setuptools, the packages list is not recursive, and sub-packages must be included explicitly (e.g. which would contain the python modules defined in the folder src/your_package/tools/my_util/, along with an file).

This is only for use with catkin. Remember not to invoke it yourself.

Put that script in the top directory of your package, and add this to your CMakeLists.txt:


That takes care of installing your Python modules. Never use it to install executable scripts. Use the catkin_install_python() command shown above.