概要
Pythonにはpipenvだね(自分とこの環境下におけるPython使用ルール),というわけでROS2+pipenvを使ったらモジュール関係でハマったので記載.
現象1
何が起こったのか
pipenv install
でモジュールをインストールし,ROS2で使用しようとすると「module not found」が出てしまう.
原因はなんだったのか
pipenv shell
で仮想環境に入ると,その仮想環境内でインストールしたmoduleは当然見える.具体的には「その仮想環境のディレクトリ/lib/Python*.*/site-packages/」に入っていて,ちゃんと見えている.ちなみに「その仮想環境のディレクトリ」はpipenv --venv
で確認できる.
しかし,ROS2の実行環境ではこれが見えていない.別環境になっている?
どうもROS2は仮想環境外のpythonを使っていて,仮想環境のパッケージのディレクトリが見えなくなっているっぽい.
どうすりゃいいのさ
とりあえず力技で解決.$PYTHONPATH
に仮想環境のディレクトリをつけてしまえ.ただ,仮想環境のディレクトリは仮想環境ごとに違うので流石に少しだけ工夫.
解決用ファイル
import os
import glob
import subprocess
venv_dir = subprocess.run(['pipenv','--venv'], capture_output=True, text=True).stdout.replace("\n","")
#print(venv_dir)
search_dir = venv_dir + "/lib/*/site-packages/"
#print(search_dir)
site_dir = glob.glob(search_dir)
#print(site_dir)
pythonpath = os.environ['PYTHONPATH']
#print(pythonpath)
for each_dir in site_dir:
pythonpath += ":"
pythonpath += each_dir
print(pythonpath)
#!/bin/bash
python_path=$(python3 setup_for_pipenv.py)
export PYTHONPATH=$python_path
解決用ファイルの使い方
新しいターミナルを起動するごとに以下を実行.要はpipenvで仮想環境に入ったら,最初の一回bashファイルを実行する.
cd ${対象のディレクトリ}
pipenv shell # 仮想環境にはいりましょう
source setup_for_pipenv.bash
適当すぎて恥ずかしいので,よりスマートな方法もとむ.
pipenvのscriptsを利用
色々コマンドうつのが面倒な場合,pipenvのscriptsを利用する手もある.
例えば,ros2の実行をros2 launch test test.py
だとすると,Pipfileのscripts,それを使ったpipenvは以下のようになる.
[[source]]
...
...
[scripts]
start = "bash -c '. install/local_setup.bash && source setup_for_pipenv.bash && ros2 launch test test.py'"
$ pipenv run start
これで仮想環境に入り,諸々実後までしてくれる.
現象2
何がおこったのか
C++とpythonを混合していて(例えばノードはpython,メッセージも作成=C++),仮想環境内でC++のコンパイルをするとき,catkin_pkgがないと怒られる.
ModuleNotFoundError: No module named 'catkin_pkg'
原因はなんだったのか
ROSはシステムのPythonを使う.基本,仮想環境は対応していない,らしい(ros answersなどに同様のエラーについていくつかポストがある).
どうすりゃいいのさ
仮想環境内で必要なモジュールをいれれば動く.
解決策
pipenv install catkin_pkg empy lark
蛇足
モジュール
他にもあったほうがいいかも?ってモジュールとして
- pandas
- matplotlib
- numpy
などがある.使うなら同じように pipenv install
でインストール.
pipenv時のpython version
できればpyenvでインストールしたものではなく,systemつかうといいかも?
なぜならROS2はsystem(OSのやつ)を使うから.
ただ,Pipfileの中に使っているpython version書かれるのでどうしたものか?