ROS2: Cannot run my Python script, "No executable found" error

I am trying to build my python package in ROS2. I have copied the code from minimal_publisher example and just changed some names. After building and trying to run it I get: No executable found.

I am building using src/ament/ament_tools/scripts/ament.py build --symlink-install --only-package rtcm_publisher
and running source ~/ros2_ws/install/local_setup.bash after build.

What am I doing wrong?

My code here:

setup.py


package_name = 'rtcm_publisher'


setup(
    name=package_name,
    version='0.4.0',
    packages=[],
    py_modules=[
        'rtcm_publisher_old'],
    data_files=[
        ('share/ament_index/resource_index/packages',
            ['resource/' + package_name]),
        ('share/' + package_name, ['package.xml']),
    ],
    install_requires=['setuptools'],
    author='Mikael Arguedas',
    author_email='mikael@osrfoundation.org',
    maintainer='Mikael Arguedas',
    maintainer_email='mikael@osrfoundation.org',
    keywords=['ROS'],
    classifiers=[
        'Intended Audience :: Developers',
        'License :: OSI Approved :: Apache Software License',
        'Programming Language :: Python',
        'Topic :: Software Development',
    ],
    description='Examples of minimal publishers using rclpy.',
    license='Apache License, Version 2.0',
    entry_points={
        'console_scripts': [
            'rtcm_publisher_old = rtcm_publisher_old:main'
        ],
    },
)

package.xml

<?xml-model href="http://download.ros.org/schema/package_format2.xsd" schematypens="http://www.w3.org/2001/XMLSchema"?>
<package format="2">
  <name>rtcm_publisher</name>
  <version>0.4.0</version>
  <description>Examples of minimal publishers using rclpy.</description>

  <maintainer email="mikael@osrfoundation.org">Mikael Arguedas</maintainer>
  <license>Apache License 2.0</license>

  <exec_depend>rclpy</exec_depend>
  <exec_depend>std_msgs</exec_depend>

  <!-- These test dependencies are optional
  Their purpose is to make sure that the code passes the linters -->
  <!-- <test_depend>ament_copyright</test_depend>
  <test_depend>ament_flake8</test_depend>
  <test_depend>ament_pep257</test_depend> -->

  <export>
    <build_type>ament_python</build_type>
  </export>
</package>

rtcm_publisher_old.py

#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

from time import sleep

import rclpy

from std_msgs.msg import String

# We do not recommend this style as ROS 2 provides timers for this purpose,
# and it is recommended that all nodes call a variation of spin.
# This example is only included for completeness because it is similar to examples in ROS 1.
# For periodic publication please see the other examples using timers.


def main(args=None):
    rclpy.init(args=args)

    node = rclpy.create_node('rtcm_publisher')

    publisher = node.create_publisher(String, 'topic')

    msg = String()

    i = 0
    while rclpy.ok():
        msg.data = 'Hello World: %d' % i
        i += 1
        node.get_logger().info('Publishing: "%s"' % msg.data)
        publisher.publish(msg)
        sleep(0.5)  # seconds

    # Destroy the node explicitly
    # (optional - otherwise it will be done automatically
    # when the garbage collector destroys the node object)
    node.destroy_node()
    rclpy.shutdown()


if __name__ == '__main__':
    main()

You didn’t mention what exact command you invoked when you got this error message.

If you are trying to call ros2 run ... that won’t work since that command expects the executable to be in the path <install-prefix>/lib/<pkgname>. Your script rtcm_publisher_old is likely being installed into <install-prefix>/bin and is therefore already on the PATH. You should be able to invoke the executable directly using just the name.

Agreed with @dirk-thomas’s comment.
I would expect your executables to be installed in bin so it should be on the PATH and can be invoked directly from the commandline.
If you want the executables to not be on the path and to be invokable using ros2 run you need to them install to <install-prefix>/lib/<pkgname>, you can specify this in the setup.cfg file: https://github.com/ros2/examples/blob/a75151ef1388b565268508228df42c06462c1337/rclpy/topics/minimal_publisher/setup.cfg

Wow, thank you both, you were right! :slight_smile: