gggggraziegrazie

graizegrazieさんのやったこと、学んだことを記録する雑記帳です

ROS in python + 仮想環境でpip installしたはずのモジュールがModuleNotFoundになる

ROSのpythonコードを実行するとき、仮想環境下で実行することが多いと思います。このとき、rosrunでコードを実行しようとすると、venv下のpythonのsite-packagesにpathが通っておらず、ModuleNotFoundになると思います。ただ、python xxx.pyのようにすれば、トラブルなくコードを実行できると思います。これは、pythonを実行すれば仮想環境下のsite-packagesにパスが通っているものの、rosrunだとROS環境下で定義された探索パスを使うことが原因です。そのため、下記の3つの呼び出し方で、それぞれsys.pathの中身を比較してみました。なお、今回はmycobot_rosというROSパッケージを使った時のログを使って示します。

  1. rosrun aaa xxx.py
  2. python3 xxx.py
  3. ./xxx.py (xxx.pyをchmod 777で実行権限を付与)

rosrun aaa xxx.py

['/home/user/catkin_ws/devel/.private/mycobot_communication/lib/mycobot_communication', '/home/user/catkin_ws/devel/lib/python3/dist-packages', '/opt/ros/noetic/lib/python3/dist-packages', '/usr/lib/python38.zip', '/usr/lib/python3.8', '/usr/lib/python3.8/lib-dynload', '/home/user/.local/lib/python3.8/site-packages', '/usr/local/lib/python3.8/dist-packages', '/usr/lib/python3/dist-packages']

python3 xxx.py

['/home/user/catkin_ws/src/mycobot_ros/mycobot_communication/scripts', '/home/user/catkin_ws/devel/lib/python3/dist-packages', '/opt/ros/noetic/lib/python3/dist-packages', '/usr/lib/python38.zip', '/usr/lib/python3.8', '/usr/lib/python3.8/lib-dynload', '/home/user/catkin_ws/src/mycobot_ros/venv/lib/python3.8/site-packages']

./xxx.py

['/home/user/catkin_ws/src/mycobot_ros/mycobot_communication/scripts', '/home/user/catkin_ws/devel/lib/python3/dist-packages', '/opt/ros/noetic/lib/python3/dist-packages', '/usr/lib/python2.7', '/usr/lib/python2.7/plat-x86_64-linux-gnu', '/usr/lib/python2.7/lib-tk', '/usr/lib/python2.7/lib-old', '/usr/lib/python2.7/lib-dynload', '/home/user/.local/lib/python2.7/site-packages', '/usr/local/lib/python2.7/dist-packages', '/usr/lib/python2.7/dist-packages']
(先頭に、#!/usr/bin/env python2、というshebangを追加しています)

上記のように、確かに仮想環境化でrosrunしても、venvの下のsite-packagesにパスが通っていないことが確認できました。sys.path.appendにvenv下のsite-packagesの絶対パスを登録すれば、今回のエラーは回避できます。もっとキレイな方法があれば、教えていただけますと幸いです。