今のところuWSGIはvirtualenvで作ったアプリ別のモジュールをロードすることは出来るものの、システムのlibpython.soを直接使っているため、そのままではビルド時のPythonしか動かない。
異なるバージョンのpythonを含むvirutalenvに入ろうとすると、PYTHONPATHが違うためimport siteの時点でモジュールのロードに失敗する。
Python version: 2.6.6 (r266:84292, Nov 22 2013, 12:16:22) [GCC 4.4.7 20120313 (Red Hat 4.4.7-4)] ... Set PythonHome to /path/to/py27env 'import site' failed; use -v for traceback
他のバージョンのpythonを使うには、対応するpythonとpythonプラグイン対応のuWSGIをビルドし直す必要がある。
ビルド手順
デフォルトのままpipなどでインストールすると、python他プラグイン全部入りのuwsgiバイナリが出来ているはず。 (pipで入れていれば/tmp/pip-build-root/uwsgiに必要なファイルが展開されているので、これを元にビルド)
uwsgiソースのbuildconfディレクトリには、uwsgi本体ビルド用の設定ファイルが含まれている。 pythonを含まないバイナリを作るには、buildconf/nolang.iniを使ってビルドするか、main_plugin=からpythonとgeventを抜いておく必要がある。(geventもpythonに依存しているためビルド出来ない)
python uwsgiconfig.py --build nolang
次にプラグインをビルドするのだが、uwsgiconfig.pyはリンクするlibpython.soをビルド時のPython環境から探しているらしく、ほしいバージョンのsharedなpythonとlibpythonがセットで必要。 さらに面倒なことにpythonビルドツールのpythonzはデフォルトではsharedなビルドを作ってくれない。(OSXは別?)
一応configureオプションを渡すことでビルドは可能で、
pythonz install 2.7.6 --verbose --configure='--enable-shared LDFLAGS="-Wl,-rpath -Wl,\\$$ORIGIN/../lib"'
あるいは手動でインストール
./configure --prefix=/usr/local/python27 --enable-shared LDFLAGS="-Wl,-rpath /usr/local/python27/lib" make sudo make altinstall
必要なバージョンのsharedなpythonバイナリでプラグインをビルド。pluginsディレクトリにプラグインのテンプレートが入っている。
python2.7 uwsgiconfig.py --plugin plugins/python nolang python27 python2.7 uwsgiconfig.py --plugin plugins/gevent nolang gevent27
これでuwsgiバイナリと*_plugin.soが出来るのでバイナリを置き換え。
sudo cp uwsgi /usr/bin/uwsgi sudo mkdir -p /usr/lib/uwsgi sudo cp *.so /usr/lib/uwsgi
アプリの設定ファイルから
[uwsgi] plugins-dir=/usr/lib/uwsgi plugin=python27_plugin.so virtualenv=/path/to/py27env chdir=/path/to/py27app
とロードさせればpython2.7を利用できる。
同様にphp-embeddedの入った環境で
python uwsgiconfig.py --plugin plugins/php nolang php
でphpプラグインもビルドできた。
ものすごく面倒なのでuwsgi側でvirtualenvから自動ロードするか、libpython.soをplugins-dirに持ってくるようにパッチを当てたい……