十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

ROS与Anaconda Python环境冲突解决:隔离配置与共存指南

ROS与Anaconda Python环境冲突解决:隔离配置与共存指南 1. 为什么ROS和Anaconda的Python冲突这么让人头疼搞ROS开发的人十个里有八个被Python环境折腾过。你装完ROS Noetic系统Python 3.8里塞满了rospy、rosbag、tf这些包跑得好好的。然后你想跑个深度学习节点需要PyTorch或者OpenCV的新版本pip install一下完了roscore起不来了。或者你装了Anacondabase环境默认Python 3.9甚至3.11一激活conda环境ROS的Python包全部找不到终端里一片红色报错。这个问题的根源在于ROS和Anaconda对Python环境的管理方式完全不同。ROS依赖系统级的Python解释器和dist-packages路径它通过/opt/ros/noetic/setup.bash设置PYTHONPATH把ROS自己的Python包路径注入进去。而Anaconda走的是另一套逻辑它有自己的site-packages有自己的Python解释器激活环境时会重写PATH和PYTHONPATH。两套体系一撞车轻则import报错重则roscore直接罢工。我见过太多人在这上面浪费时间了。有人选择不用Anaconda所有Python包都往系统环境里装结果系统Python被污染得一塌糊涂哪天想升级个numpy都怕把ROS搞崩。也有人每次跑ROS节点前手动改PYTHONPATH改来改去自己都记不清改了啥。这些做法不是不行但都不是长久之计。正确的思路其实很清晰让ROS活在系统Python里让Anaconda虚拟环境专门承载你的算法开发依赖两者通过合理的环境隔离和路径管理共存。听起来简单但实际操作中有不少细节需要注意比如conda环境的Python版本选择、PYTHONPATH的拼接顺序、catkin_make时用的是哪个Python等等。下面我会把整套流程拆开讲清楚从环境规划到具体配置再到实际项目中的验证方法一步步来。这篇文章适合所有在Ubuntu上做ROS开发、同时需要用Anaconda管理Python依赖的人。不管你是刚装完ROS的新手还是已经被包冲突折磨过的老手应该都能从中找到可以直接用的方案。2. 环境规划先想清楚再动手2.1 核心原则ROS用系统的算法用conda的在动手之前先把一个核心原则刻在脑子里ROS相关的Python包永远走系统Python算法开发相关的包走conda虚拟环境。这条原则决定了后面所有的配置逻辑。为什么这么分因为ROS的Python包rospy、rospkg、cv_bridge等是通过apt安装到系统dist-packages里的它们和ROS的C库、消息定义、launch文件紧密耦合。你把这些包搬到conda环境里理论上可行但实际操作中会遇到各种动态链接库找不到的问题尤其是cv_bridge这种依赖OpenCV的包conda里的OpenCV版本和ROS编译时用的版本一旦不一致直接段错误。反过来PyTorch、TensorFlow、最新的numpy、scipy这些算法依赖放在conda环境里管理是最舒服的。conda可以精确控制版本可以创建多个隔离环境做不同项目的实验不会互相干扰。所以整个方案的架构是这样的系统Python 3.8Ubuntu 20.04默认承载ROS Noetic的全部Python依赖Conda虚拟环境比如叫ros_ml承载PyTorch、OpenCV-python、matplotlib等算法包两者通过PYTHONPATH的合理拼接实现共存ROS节点运行时能看到系统ROS包同时也能import conda环境里的算法包2.2 Python版本怎么选Ubuntu 20.04对应的ROS Noetic用的是Python 3.8这是硬性要求没得商量。所以你的conda环境Python版本最好也选3.8这样能最大程度避免ABI兼容性问题。有人会问我用Python 3.9或3.10行不行技术上可以但你会遇到一些麻烦。比如某些ROS的Python包在编译时绑定了3.8的C API你在3.9环境里import可能会报undefined symbol。另外catkin_make在编译Python节点时默认调用的是/usr/bin/python3也就是系统Python 3.8如果你的conda环境是3.9编译产物和运行环境就对不上了。所以我的建议很明确conda环境的Python版本选3.8。创建命令conda create -n ros_ml python3.8如果你确实需要更高版本的Python来做某些特定任务那就单独再建一个环境不要和ROS混在一起用。2.3 Anaconda装在哪要不要加到bashrcAnaconda的安装位置建议放在用户目录下比如~/anaconda3不要装到/opt下面。原因很简单权限问题。装到系统目录下以后conda install的时候可能需要sudo而sudo会改变环境变量容易出幺蛾子。安装的时候有一个关键选择不要勾选“Add Anaconda to my PATH environment variable”。这个选项会把conda的base环境永久加到PATH最前面导致你每次开终端都默认激活base环境系统Python被覆盖ROS直接找不到。正确的做法是让安装程序把conda初始化写到.bashrc里但默认不激活base环境。安装完成后手动在.bashrc里加上conda config --set auto_activate_base false这样你开终端时不会自动进base环境需要的时候再conda activate。2.4 整体配置流程图在脑子里过一遍完整的配置流程确认系统Python和ROS环境正常roscore能跑python3 -c import rospy不报错安装Anaconda设置auto_activate_base false创建Python 3.8的conda虚拟环境在虚拟环境中安装算法依赖PyTorch、OpenCV等配置ROS节点的运行环境确保PYTHONPATH同时包含ROS系统路径和conda环境路径验证在conda环境中能import rospy也能import torch在实际ROS节点中测试确保消息收发正常这个流程看起来不复杂但每一步都有坑。下面我逐个拆解。3. 手把手配置从零到能跑3.1 确认ROS环境本身没问题在折腾Anaconda之前先确保ROS本身是好的。打开终端不要激活任何conda环境执行source /opt/ros/noetic/setup.bash roscore如果roscore能正常启动另开一个终端python3 -c import rospy; print(rospy.__file__)应该输出类似/opt/ros/noetic/lib/python3/dist-packages/rospy/__init__.py的路径。这说明系统Python能找到ROS的包。如果这一步就报错那先别急着装Anaconda先把ROS环境修好。常见问题包括PYTHONPATH被其他软件改过、系统Python版本不对、ROS安装不完整等。3.2 Anaconda安装与基础配置下载Anaconda安装脚本用bash执行。安装过程中注意两个点安装路径用默认的~/anaconda3就行最后一步问你要不要conda init选yes但装完后立刻设置auto_activate_base false安装完成后关掉终端重新开一个确认which conda # 应该输出 ~/anaconda3/bin/conda 或类似路径 conda --version # 输出版本号 echo $PATH | grep conda # 应该能看到conda的路径但不应该在系统路径之前然后设置国内镜像源不然conda install会慢到让你怀疑人生conda config --add channels https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/main/ conda config --add channels https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/free/ conda config --set show_channel_urls yes注意镜像源地址可能会变化如果上面的地址失效了去对应镜像站查最新的配置命令。另外有些企业内网会屏蔽外部镜像这种情况需要配置内部源。3.3 创建ROS专用的conda虚拟环境创建环境的时候指定Python 3.8conda create -n ros_ml python3.8 conda activate ros_ml激活后确认Python版本python --version # Python 3.8.x which python # ~/anaconda3/envs/ros_ml/bin/python这时候如果你直接import rospy会报ModuleNotFoundError。这是正常的因为conda环境里没有ROS的包路径。接下来就要解决这个问题。3.4 安装算法依赖包在conda环境里安装你需要的算法包。以PyTorch和OpenCV为例# 安装PyTorch根据你的CUDA版本选择对应命令 conda install pytorch torchvision torchaudio cudatoolkit11.3 -c pytorch # 安装OpenCV pip install opencv-python opencv-contrib-python # 安装其他常用包 pip install numpy scipy matplotlib scikit-learn这里有一个关键点opencv-python和ROS的cv_bridge可能会冲突。cv_bridge是ROS用来在ROS图像消息和OpenCV图像格式之间转换的包它依赖系统安装的OpenCV通过apt安装的libopencv-dev。而你在conda环境里pip install的opencv-python是另一个独立的OpenCV副本。这两个OpenCV版本如果不一致cv_bridge在转换图像时可能会崩溃。解决方案有两个方案一conda环境里不装opencv-python直接用系统的cv2。但这样你就用不了conda环境里的OpenCV新特性。方案二conda环境里装opencv-python但在ROS节点中涉及cv_bridge的部分确保使用的是系统OpenCV的API。实际操作中只要版本差异不太大比如都是4.x通常能正常工作。如果遇到段错误再考虑降级或统一版本。我个人的做法是conda环境里装opencv-python用于纯算法开发ROS节点里如果需要cv_bridge就单独测试确认没问题再用。3.5 配置PYTHONPATH实现共存这是整个方案最核心的一步。目标是在conda环境激活的状态下Python既能找到ROS的包也能找到conda的包。ROS的包在/opt/ros/noetic/lib/python3/dist-packagesconda的包在~/anaconda3/envs/ros_ml/lib/python3.8/site-packages。Python的模块搜索路径由sys.path决定而sys.path受PYTHONPATH环境变量影响。默认情况下conda激活时会设置PYTHONPATH为空或只包含conda相关路径。我们需要把ROS的路径加进去。最直接的方法是在.bashrc里加一段逻辑# 在.bashrc末尾添加 if [ -n $CONDA_DEFAULT_ENV ]; then export PYTHONPATH/opt/ros/noetic/lib/python3/dist-packages:$PYTHONPATH fi但这样有个问题每次激活conda环境都会往PYTHONPATH里追加多次激活会导致重复。更好的做法是在conda环境的激活脚本里设置。找到conda环境的激活目录ls ~/anaconda3/envs/ros_ml/etc/conda/activate.d/如果没有这个目录就创建一个mkdir -p ~/anaconda3/envs/ros_ml/etc/conda/activate.d mkdir -p ~/anaconda3/envs/ros_ml/etc/conda/deactivate.d然后创建激活脚本# ~/anaconda3/envs/ros_ml/etc/conda/activate.d/ros_env.sh #!/bin/bash export ROS_PYTHON_PATH_OLD$PYTHONPATH export PYTHONPATH/opt/ros/noetic/lib/python3/dist-packages:$PYTHONPATH创建去激活脚本# ~/anaconda3/envs/ros_ml/etc/conda/deactivate.d/ros_env.sh #!/bin/bash export PYTHONPATH$ROS_PYTHON_PATH_OLD unset ROS_PYTHON_PATH_OLD这样每次conda activate ros_ml时ROS的Python路径会自动加到PYTHONPATH前面conda deactivate时自动恢复。注意脚本文件需要可执行权限虽然conda激活时是source执行但养成习惯加上chmod x没坏处。3.6 验证配置是否生效激活环境检查PYTHONPATHconda activate ros_ml echo $PYTHONPATH # 应该包含 /opt/ros/noetic/lib/python3/dist-packages然后测试importpython -c import rospy; print(rospy OK) python -c import torch; print(torch OK) python -c import cv2; print(cv2 OK)如果三个都OK说明基本配置成功了。如果rospy报错检查PYTHONPATH是否设置正确如果torch报错检查conda环境里是否安装了torch。还有一个隐藏的坑rospkg包。ROS的很多工具依赖rospkg它可能在系统Python里有但conda环境里没有。如果报ModuleNotFoundError: No module named rospkg在conda环境里pip install一下pip install rospkg但要注意pip安装的rospkg版本可能和ROS自带的版本不一致如果遇到兼容性问题可以考虑从系统路径复制或者用conda install指定版本。4. 实际项目中的验证与调试4.1 写一个简单的ROS节点测试配置完了不能只看import得实际跑一个ROS节点。创建一个简单的发布者节点#!/usr/bin/env python3 import rospy from std_msgs.msg import String import torch import numpy as np def talker(): pub rospy.Publisher(chatter, String, queue_size10) rospy.init_node(talker, anonymousTrue) rate rospy.Rate(1) # 测试torch和numpy是否可用 x torch.tensor([1.0, 2.0, 3.0]) y np.array([4.0, 5.0, 6.0]) rospy.loginfo(ftorch tensor: {x}, numpy array: {y}) while not rospy.is_shutdown(): msg String() msg.data fhello at {rospy.get_time()} pub.publish(msg) rate.sleep() if __name__ __main__: try: talker() except rospy.ROSInterruptException: pass给文件加执行权限然后运行chmod x talker.py conda activate ros_ml source /opt/ros/noetic/setup.bash python talker.py如果能看到日志输出并且rostopic echo /chatter能收到消息说明整个链路是通的。4.2 catkin_make时的Python选择如果你用catkin_make编译工作空间注意它默认调用的是系统Python。这通常没问题因为ROS的C编译不依赖conda环境。但如果你有Python节点需要编译安装catkin会使用/usr/bin/python3。如果你希望catkin_make使用conda环境的Python可以这样conda activate ros_ml catkin_make -DPYTHON_EXECUTABLE$(which python) -DPYTHON_INCLUDE_DIR$(python -c from distutils.sysconfig import get_python_inc; print(get_python_inc())) -DPYTHON_LIBRARY$(python -c import distutils.sysconfig as sysconfig; print(sysconfig.get_config_var(LIBDIR)))但我不推荐这么做。原因前面说过ROS的Python包和系统Python绑定用conda的Python编译可能会引入难以排查的问题。除非你有明确需求否则catkin_make就用系统Python运行时再用conda环境。4.3 在launch文件中指定Python解释器ROS的launch文件默认用系统Python运行节点。如果你想让某个节点在conda环境中运行可以在launch文件中指定launch node nametalker pkgmy_pkg typetalker.py outputscreen launch-prefixbash -c source ~/anaconda3/etc/profile.d/conda.sh conda activate ros_ml $0 $/ /launch这个launch-prefix会在启动节点前先激活conda环境。但要注意这样启动的节点其PYTHONPATH会包含conda环境的路径如果节点里import了ROS包需要确保PYTHONPATH里也有ROS的路径通过前面配置的activate.d脚本自动处理。4.4 常见报错与排查实际使用中会遇到各种报错我整理了一个速查表报错信息可能原因解决方法ModuleNotFoundError: No module named rospyPYTHONPATH未包含ROS路径检查activate.d脚本确认PYTHONPATH设置正确ImportError: libopencv_core.so.4.2: cannot open shared object fileconda的OpenCV和系统OpenCV版本冲突统一版本或设置LD_LIBRARY_PATHundefined symbol: _Py_DeallocPython版本不匹配确保conda环境Python版本和ROS一致3.8rospkg not foundconda环境缺少rospkgpip install rospkgcv_bridge段错误OpenCV版本冲突检查cv_bridge链接的OpenCV版本必要时重装roscore启动失败conda base环境覆盖了系统Python设置auto_activate_base false提示遇到报错先看echo $PYTHONPATH和which python确认当前用的是哪个Python路径对不对。大部分问题都是路径问题。4.5 一个实际项目的配置记录我之前做一个机械臂视觉抓取的项目ROS Noetic PyTorch OpenCV。配置过程大致如下系统环境Ubuntu 20.04 ROS Noetic系统Python 3.8Anaconda装在~/anaconda3base环境Python 3.9设置不自动激活创建conda环境arm_visionPython 3.8安装PyTorch 1.12 CUDA 11.3opencv-python 4.5.5配置activate.d脚本把ROS的dist-packages加到PYTHONPATH在launch文件中用launch-prefix激活conda环境测试节点能正常订阅相机话题用cv_bridge转换图像用PyTorch做推理发布抓取位姿整个过程中遇到的主要问题是cv_bridge和opencv-python的版本冲突。系统OpenCV是4.2conda里装的是4.5.5cv_bridge在转换图像时偶尔崩溃。最后的解决方案是在conda环境里也装一个4.2版本的opencv-python保持版本一致。虽然损失了一些新特性但稳定性大大提升。这个经验告诉我版本一致性比版本新更重要。尤其是在ROS这种对依赖敏感的框架里不要盲目追求最新版本。5. 进阶技巧与长期维护5.1 用environment.yml管理环境conda环境配置好后导出为yml文件方便迁移和重建conda env export -n ros_ml ros_ml_env.yml但这个文件会包含很多本地路径和版本号跨机器使用时可能需要手动编辑。更推荐的做法是手写一个精简的environment.ymlname: ros_ml channels: - pytorch - defaults dependencies: - python3.8 - pytorch1.12 - torchvision0.13 - cudatoolkit11.3 - numpy1.21 - pip - pip: - opencv-python4.2.0.34 - rospkg这样重建环境时conda env create -f environment.yml5.2 多环境管理策略如果你同时做多个ROS项目每个项目依赖不同的Python包版本可以创建多个conda环境ros_ml_pytorchPyTorch项目ros_ml_tfTensorFlow项目ros_ml_basic基础算法开发每个环境都配置相同的activate.d脚本把ROS路径加进去。这样切换环境时ROS的基础功能始终可用只是算法包不同。但要注意环境太多会占用大量磁盘空间。每个conda环境大概2-5GB如果装了大量包可能更大。定期清理不用的环境conda env list conda env remove -n old_env5.3 与VSCode的配合在VSCode里开发ROS Python节点时需要正确配置Python解释器。打开命令面板选择Python: Select Interpreter找到conda环境的Python路径~/anaconda3/envs/ros_ml/bin/python然后在VSCode的settings.json里配置终端自动激活conda环境{ python.terminal.activateEnvironment: true, terminal.integrated.shell.linux: /bin/bash }这样在VSCode里打开终端时会自动激活conda环境PYTHONPATH也会正确设置。但VSCode的Python插件有时会用自己的方式解析import路径如果出现import报错但终端里能跑的情况检查VSCode的python.analysis.extraPaths设置把ROS的dist-packages路径加进去{ python.analysis.extraPaths: [ /opt/ros/noetic/lib/python3/dist-packages ] }5.4 长期维护的注意事项这套方案跑起来之后日常维护有几个点要注意不要随意升级conda环境的Python版本。一旦环境创建好Python版本就固定了。升级Python版本会导致所有已安装的包需要重装而且可能引入兼容性问题。定期检查ROS和conda的路径优先级。有时候安装新软件会修改.bashrc可能影响PYTHONPATH的设置。如果突然出现import报错先检查环境变量。备份environment.yml。把每个项目的conda环境配置导出备份万一环境损坏可以快速重建。注意磁盘空间。conda的包缓存会占用大量空间定期清理conda clean --all记录配置变更。每次修改activate.d脚本或安装新包在项目的README里记一笔。过几个月回头看这些记录能帮你快速回忆起当时的配置逻辑。5.5 一个容易忽略的细节ROS_PACKAGE_PATH除了PYTHONPATHROS还依赖ROS_PACKAGE_PATH来查找功能包。这个变量通常由source /opt/ros/noetic/setup.bash和source devel/setup.bash设置。在conda环境中这个变量不受影响因为conda不会修改它。但如果你在conda环境里运行rospack find之类的命令确保ROS_PACKAGE_PATH已经正确设置。可以在activate.d脚本里也加上export ROS_PACKAGE_PATH/opt/ros/noetic/share:$ROS_PACKAGE_PATH不过通常不需要因为source setup.bash已经处理了。这里提一下是为了让你知道如果遇到rospack找不到包的问题检查这个变量。5.6 关于鱼香ROS一键安装的说明网上有很多一键安装ROS的工具比如鱼香ROS的脚本。这些工具确实方便能帮你快速装好ROS环境。但要注意一键安装脚本通常不会考虑Anaconda的共存问题。如果你先用一键脚本装了ROS再装Anaconda可能会遇到环境冲突。我的建议是无论用什么方式装ROS装完后先验证系统Python能正常import rospy然后再装Anaconda。如果顺序反了先把Anaconda的base环境禁用确保系统Python是干净的再验证ROS。另外一键安装脚本可能会修改.bashrc加入source ROS setup.bash的行。这本身没问题但如果你在.bashrc里同时有conda init和ROS setup要注意它们的顺序。通常ROS的source应该在conda init之前这样conda激活时不会覆盖ROS的环境变量。实际配置中我习惯把ROS的source放在.bashrc靠前的位置conda init放在后面。然后在conda的activate.d脚本里处理PYTHONPATH的拼接。这样逻辑最清晰出问题也容易排查。5.7 性能考量conda环境对ROS节点运行的影响有人担心在conda环境里跑ROS节点会影响性能。实测下来影响微乎其微。Python的import路径多了一层查找但只在启动时有一次开销运行时的函数调用没有额外损耗。PyTorch的CUDA运算性能也不受conda环境影响只要CUDA版本和驱动匹配就行。唯一需要注意的是内存占用。conda环境里的Python解释器可能比系统Python稍大一些但对于现代机器来说这点差异可以忽略。真正影响性能的是算法本身和ROS节点的设计。比如图像传输用压缩格式还是原始格式、推理是在CPU还是GPU上跑、消息队列大小设置是否合理。这些才是需要花精力优化的地方。5.8 从conda迁移到venv的考虑有些团队可能不想引入Anaconda这么重的工具考虑用Python自带的venv。技术上可行配置逻辑类似创建venv在激活脚本里设置PYTHONPATH安装依赖包。但venv有几个劣势不能像conda那样管理非Python依赖比如CUDA toolkit不能跨平台一致地管理环境包版本解析能力也不如conda。如果你只是做纯Python开发venv够用但如果涉及深度学习、CUDA、复杂的科学计算依赖conda还是更省心。我个人的选择是ROS开发用conda轻量级Python脚本用venv根据项目需求灵活切换。关键是理解背后的环境隔离原理工具只是手段。5.9 一个真实的踩坑记录最后分享一个我踩过的坑。有一次配置好环境后一切正常跑了几天都没问题。然后某天突然所有ROS节点都报ImportError: No module named rospy。检查PYTHONPATH发现ROS的路径不见了。排查了半天发现是conda自动更新了。conda在后台自动更新时重写了activate.d目录下的脚本把我手动加的ros_env.sh覆盖了。解决方案是关闭conda的自动更新conda config --set auto_update_conda false然后重新创建activate.d脚本。这个坑让我意识到任何自动化工具都可能在不经意间修改你的配置。重要的配置脚本最好在版本控制里备份一份出问题了能快速恢复。另外conda的环境激活脚本在conda版本升级后可能会改变行为。如果升级conda后环境出问题检查etc/conda/activate.d/目录下的脚本是否还在内容是否被修改。这些经验都是实际项目中积累的希望对你有帮助。配置环境这件事第一次搞清楚了后面就是重复劳动。关键是理解原理知道每个步骤在做什么出问题了知道去哪里找原因。
返回列表