pythonclassimportrosrospy

cannot import name 'ClassName' from 'PythonFile' using ROS Noetic


I'm using Python 3.8.10 and Ubuntu 20.04, I'm getting this Error:

Traceback (most recent call last):
  File "/home/belal/git/decision_making_pacbot/devel/lib/ros_planning/ros_plan.py", line 15, in <module>
    exec(compile(fh.read(), python_script, 'exec'), context)
  File "/home/belal/git/decision_making_pacbot/src/ros_planning/src/ros_planning/ros_plan.py", line 8, in <module>
    from problem_handler import ProblemHandler
ImportError: cannot import name 'ProblemHandler' from 'problem_handler' (/home/belal/git/decision_making_pacbot/devel/.private/ros_planning/lib/ros_planning/problem_handler.py)

My files hierarchy is as follows:

src
├── ros_planning
│   ├── CMakeLists.txt
|   ├── package.xml
|   ├── setup.py
│   └── src
│       └── ros_planning
|           ├── ros_plan.py
|           ├──problem_handler.py
|           └──__init__.py

My CMakeLists.txt

cmake_minimum_required(VERSION 3.0.2)
project(ros_planning)

# Load catkin and all dependencies required for this package
find_package(catkin REQUIRED COMPONENTS
    rospy
)

# Declare catkin package
catkin_package(
  CATKIN_DEPENDS
)

catkin_install_python(PROGRAMS
  src/${PROJECT_NAME}/problem_handler.py
  src/${PROJECT_NAME}/ros_plan.py
  DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
)
catkin_python_setup()

install(
  DIRECTORY model downward launch
  DESTINATION "${CATKIN_PACKAGE_SHARE_DESTINATION}"
)

My package.xml

<?xml version="1.0"?>
<package format="2">
  <name>ros_planning</name>
  <version>0.0.0</version>
  <description>The ros_planning package</description>

  <maintainer email="s@todo.todo">s</maintainer>

  <license>MIT</license>

  <buildtool_depend>catkin</buildtool_depend>
  <build_depend>roscpp</build_depend>
  <build_depend>rospy</build_depend>
  <build_depend>std_msgs</build_depend>
  <build_export_depend>roscpp</build_export_depend>
  <build_export_depend>rospy</build_export_depend>
  <build_export_depend>std_msgs</build_export_depend>
  <exec_depend>roscpp</exec_depend>
  <exec_depend>rospy</exec_depend>
  <exec_depend>std_msgs</exec_depend>

</package>

My setup.py

#!/usr/bin/python3

from distutils.core import setup
from catkin_pkg.python_setup import generate_distutils_setup

# fetch values from package.xml
setup_args = generate_distutils_setup(
    scripts=['src/ros_planning/problem_handler.py', 'src/ros_planning/ros_plan.py'],
    packages=['ros_planning'],
    package_dir={'': 'src'},
    requires=['rospy', 'std_msgs']
)

setup(**setup_args)

and finally inside ros_plan.py I'm importing the class from problem_handler import ProblemHandler which exists in problem_handler.py as follows:

class ProblemHandler:
    def __init__(self, path):
        self.path = path

Can you please tell me how can I import my python class properly in ROS? Because a similar setup is working well with me on ROS Melodic!

Here is the problem_handler.py in the devel folder generated by ROS:

#!/usr/bin/python3
# -*- coding: utf-8 -*-
# generated from catkin/cmake/template/script.py.in
# creates a relay to a python script source file, acting as that file.
# The purpose is that of a symlink
python_script = '/home/belal/git/decision_making_pacbot/src/ros_planning/src/ros_planning/problem_handler.py'
with open(python_script, 'r') as fh:
    context = {
        '__builtins__': __builtins__,
        '__doc__': None,
        '__file__': python_script,
        '__name__': __name__,
        '__package__': None,
    }
    exec(compile(fh.read(), python_script, 'exec'), context)

and when I print the path of execution of ros_plan.py using os.getcwd() I get/home/$USER/.ros


Solution

  • The solution in my case was to import the class as follows:

    from ros_package_name.script_name import className

    from ros_planning.problem_handler import ProblemHandler