boost.python: os.environ and LD_LIBRARY_PATH | Chandler@Berlin

Chandler@Berlin

ベルリン在住

さて,今回もプログラムの詳細なので,興味のない方はまたどこかでお会いしましょう.

私が最初に書いている python のコードはテストスイートである.Martin Fowler が好きな私は,新しいプロジェクトをテストとドキュメントとinterface を書くことから初める.

今回は os.environ and LD_LIBRARY_PATH の話である.これはboost.python の 話でもある.以下は Linux 環境の話である.python では環境変数を os.environ で変更できる.たとえば,環境変数LD_LIBRARY_PATH を変更したけ れば,

os.environ['LD_LIBRARY_PATH'] = '/some/directory/lib'

とすれば良い.これで LD_LIBRARY_PATH を変更したと思っていた私は問題につ きあたった.私の職場ではソフトウェアを install する権限は developer にないため,たとえば boost を使いたいとか python を bind したいなどという 場合には管理者権限なしでなんとかしなくてはならない.したがって sharedライブラリのパスの設定は重要になってくる.

私の project には,以下のようなディレクトリ構造があった.

test_x +--+ pymodule +--+ mypython_binding_module.so
+--+ testbase +--+ test_run.py
+--+ boost144 +--+ lib +--+ ...
+--+ libboost_python.so

ここで問題は,mypython_binding_module.so は libboost_python.so に依存し ていることである.ライブラリパスは環境変数を用いて設定することが多いが,環境変数は global かつ implicit な効果があるため,私は環境変数が苦手で ある.どうせ設定するならば,python の内部でなんとかできないかと考えた.

mypython_binding_module.so は python からは python のモジュールに見えるので.これを import するには,sys.path を設定すれば良い.一方でmypython_binding_module.so は libboost_python.so に依存しており,これをload する必要がある.しかし,libboost_python.so は python の module ではない.そのため,sys.path ではなく,LD_LIBRARY_PATH を使って,dlopenにその旨を伝える必要がある.

LD_LIBRARY_PATH は os.environ で設定できるので,問題はなさそうであるが,これは上手くいかない.最初は python 側では変更したように見えるが,実際の環境変数は変化していないのかと思ったが,どうやらそうでもないらしい.問題は dlopen にあった.マニュアルによれば,dlopen はプログラム起動時にLD_LIBRARY_PATH をチェックし,プロセスから LD_LIBRARY_PATH を変更してもその影響を受けないようだ.セキュリティを考えるともっともな仕様である.

これがわかったので,os.environ で LD_LIBRARY_PATH を変更した後に,子プロセスを作ってみると,LD_LIBRARY_PATH の変更が反映された.

つまり,環境変数を変更することは可能だが,それが反映されるかどうかは別の問題である.わかってみるとなんでもないことだが,なかなか気がつかず,二日も費やしてしまった.

ところで,ライブラリパスの設定などはよくありそうな問題である.site などのドキュメントなどは一応目を通したが,私は Python をはじめてまだ三週間目と日が浅いため,何か見落としがあるかもしれない.