Different Python versions under the same uwsgi Emperor?

Solution 1:

Well, since I wasn't exactly overwhelmed by responses, here is the solution I came up with myself:

First, I created a new virtualenv with a Python 3 interpreter:

mkvirtualenv -p /usr/bin/python3 python3env

Then I installed the stock uwsgi from Pypi, which gets compiled automatically with a Python 3 interpreter:

pip install uwsgi

I created a configuration directory /etc/uwsgi-python3 that contains the emperor.ini and a subdirectory vassals, containing vassal.ini. Finally, I added the following line to /etc/rc.local

/home/user/.virtualenvs/python3env/bin/uwsgi --ini /etc/uwsgi-python3/emperor.ini

Now there's an uwsgi Emperor running that uses the Python 3 interpreter for its vassals. It doesn't interfere with another uwsgi Emperor that was already running and uses the Python 2.7 interpreter.

I know it's not optimal, because I'm not using the pluggable interpreter architecture that's explained in the documentation (thanks roberto! I don't know how I could've overlooked that). However, it runs flawlessly and I didn't have to touch my existing uwsgi installation that's serving a bunch of production apps.

Solution 2:

Under osx i made like this. I unistalled all uwsgi on my system (from brew from pip etc).

After that i downloaded under /usr/local the source code

wget https://projects.unbit.it/downloads/uwsgi-latest.tar.gz
tar zxvf uwsgi-latest.tar.gz

after

cd uwsgi-2.0.17
make PROFILE=nolang

In this way i created an executable without plugins for python.

After that i made each plugin for each version on my system:

PYTHON=python3.6 ./uwsgi --build-plugin "plugins/python python36"
PYTHON=python2.7 ./uwsgi --build-plugin "plugins/python python27"
PYTHON=python2.6 ./uwsgi --build-plugin "plugins/python python26"

Now i have 3 plugins.

In my ini files for the emperor i specified the plugins dir and the plugin version for each file

[uwsgi]
plugins-dir = /usr/local/uwsgi-2.0.17
plugin = python36

[uwsgi]
plugins-dir = /usr/local/uwsgi-2.0.17
plugin = python27

[uwsgi]
plugins-dir = /usr/local/uwsgi-2.0.17
plugin = python26

...

I symlinked the uwsgi binary in my /usr/local folder

ln -s /usr/local/uwsgi-2.0.17/uwsgi /usr/local/bin/uwsgi

And after run the emperor

uwsgi --emperor /PATH/TO/INI/FILES/FOLDER/

And voila now i can run python26, python27 and python36 project simultaneously


Solution 3:

Another possible solution is to reuse the system-wide "emperor", and only substitute the vassal with the new version. This way you don't need to invent any new folders under /etc nor launch new services to rc.local.

  1. Install uwsgi via pip into a virtualenv.
  2. Edit the /etc/uwsgi/apps-enabled/your-app.ini as follows:

    • Remove the plugins=... line (because pip-compiled uwsgi does not support plugins).
    • Add the line:

      unprivileged-binary-patch = /path/to/your/venv/bin/uwsgi
      

      This will force the uWSGI emperor launch your own uwsgi binary as the vassal.

  3. Reload your app in the emperor service uwsgi restart your-app.

The last step somewhy reports a failure to restart the server:

 * Starting app server(s) uwsgi
   ...fail!

However, in reality, the new vassal starts fine as well as all the other apps. I did not find the time to debug this.