ROS2节点无法导入configs模块问题求助(含项目结构及排查记录)
ROS2 Humble节点导入configs模块失败问题排查与解决
问题背景
开发ROS2 Humble项目时,遇到节点无法导入configs包内模块的问题,以下是详细信息:
项目结构
test_ws/ ├── src/ │ └── test_package/ │ ├── configs/ │ │ ├── __init__.py │ │ └── global_settings.py │ ├── test_package/ │ │ ├── __init__.py │ │ ├── gps_path_planning_node.py │ │ └── scripts/ │ │ ├── __init__.py │ │ └── utils.py │ ├── package.xml │ ├── setup.cfg │ └── setup.py
报错信息
执行ros2 launch test_package simulation_launch.py启动节点时出现:
[gps_path_planning_node-5] Traceback (most recent call last): [gps_path_planning_node-5] File "/home/hiber/Desktop/test_ws/install/test_package/lib/test_package/gps_path_planning_node", line 33, in <module> [gps_path_planning_node-5] sys.exit(load_entry_point('test-package==0.0.0', 'console_scripts', 'gps_path_planning_node')()) ... [gps_path_planning_node-5] ModuleNotFoundError: No module named 'configs'
关键代码片段
gps_path_planning_node.py:
from rclpy.node import Node import rclpy from configs import global_settings from test_package.scripts.utils import * class GPSPathPlanningNode(Node): def __init__(self): super().__init__('gps_path_planning_node') self.max_speed = EGO_VEHICLE_MAX_SPEED self._logger.info('Successfully launched!') def main(args=None): rclpy.init(args=args) node = GPSPathPlanningNode() rclpy.spin(node) node.destroy_node() rclpy.shutdown() if __name__ == '__main__': main()
setup.py:
import os from setuptools import setup PACKAGE_NAME = 'test_package' def generate_data_files(share_path, data_files_path): data_files_temp = [] for path, _, files in os.walk(data_files_path): data_file = ( os.path.dirname(os.path.dirname(share_path)) + '/' + path, [ os.path.join(path, file) for file in files if not file.startswith('.') ] ) data_files_temp.append(data_file) return data_files_temp data_files = [] data_files.append(('share/ament_index/resource_index/packages', ['resource/' + PACKAGE_NAME])) data_files.append(('share/' + PACKAGE_NAME, ['package.xml'])) data_files += generate_data_files('share/' + PACKAGE_NAME + '/configs/', 'configs/') data_files += generate_data_files('share/' + PACKAGE_NAME + '/launch/', 'launch/') data_files += generate_data_files('share/' + PACKAGE_NAME + '/resource/', 'resource/') setup( name=PACKAGE_NAME, version='0.0.0', packages=[PACKAGE_NAME], data_files=data_files, install_requires=['setuptools'], zip_safe=True, maintainer='hiber', maintainer_email='...', description='TODO: Package description', license='TODO: License declaration', tests_require=['pytest'], entry_points={ 'console_scripts': [ # 'ackermann_keyboard_teleop_node = test_package.ackermann_keyboard_teleop_node:main', 'gps_path_planning_node = test_package.gps_path_planning_node:main', 'projection_weight_matrices_node = test_package.projection_weight_matrices_node:main', 'surround_view_node = test_package.surround_view_node:main', ], }, )
环境信息
- ROS2版本:Humble
- Python版本:3.10
- 操作系统:Ubuntu 22.04
已执行排查步骤
- 将
global_settings.py移至gps_path_planning_node.py同目录,修改导入语句为from test_package.global_settings import *,但scripts目录下的utils.py仍无法找到; - 检查setup.py,确认已包含test_package及scripts等子包;
- 执行
colcon clean后运行colcon build --symlink-install,并source工作空间; - 本地测试
python3 -c 'from test_package.global_settings import *; print("Import successful")'无报错; - 确认
install/test_package/lib/python3.10/site-packages/test_package/路径应包含configs、scripts等模块; - 所有目录均包含
__init__.py文件; - 尝试多种导入方式(相对导入、绝对导入、动态导入)。
问题原因与解决方案
1. 核心原因
当前setup.py中,packages=[PACKAGE_NAME]只声明了根级的test_package包,但**configs和scripts是独立于内部test_package目录的同级目录,未被声明为Python子包**;同时你把configs作为数据文件安装到了share目录,而非Python包路径下,导致ROS2节点运行时无法在Python搜索路径中找到这些模块。另外,代码中的from configs import global_settings是绝对导入,但configs并未注册为Python包,不在Python搜索路径内。
2. 具体修复步骤
步骤1:调整项目结构(推荐)
将configs和scripts目录移动到内部的test_package目录下,使其成为test_package的子包:
test_ws/ ├── src/ │ └── test_package/ │ ├── test_package/ │ │ ├── __init__.py │ │ ├── gps_path_planning_node.py │ │ ├── configs/ │ │ │ ├── __init__.py │ │ │ └── global_settings.py │ │ └── scripts/ │ │ ├── __init__.py │ │ └── utils.py │ ├── package.xml │ ├── setup.cfg │ └── setup.py
步骤2:修改setup.py,正确声明所有子包
将packages参数改为自动发现所有子包,或显式列出:
# 替换原来的packages=[PACKAGE_NAME] packages=setuptools.find_packages(), # 或者显式列出: # packages=['test_package', 'test_package.configs', 'test_package.scripts'],
同时移除data_files中关于configs的部分,因为它现在是Python包的一部分,无需作为数据文件安装:
# 删除这一行 # data_files += generate_data_files('share/' + PACKAGE_NAME + '/configs/', 'configs/')
步骤3:修改导入语句
调整gps_path_planning_node.py中的导入路径为绝对子包导入:
# 替换原来的from configs import global_settings from test_package.configs import global_settings # scripts的导入可保持不变,或改为相对导入:from .scripts.utils import *
步骤4:重新构建并source
colcon clean colcon build --symlink-install source install/setup.bash
3. 不调整目录结构的替代方案
若坚持保留原目录结构,需将configs和scripts声明为独立Python包:
- 在
setup.py的packages中添加这两个包:
packages=[PACKAGE_NAME, 'configs', 'scripts'],
- 保持
from configs import global_settings导入语句不变,确保configs和scripts目录下的__init__.py存在; - 重新构建并source工作空间。
内容的提问来源于stack exchange,提问作者Gonam Salinsky
相关产品推荐
相关产品推荐

