Python – Different Python versions under the same uwsgi Emperor

pythonuwsgivirtualenv

I'm running an uwsgi Emperor with various Vassals that each serve a specific Python app from a different virtualenv. Since uwsgi was compiled with it's own Python 2.7 interpreter, trying to use a virtualenv with Python 3 in it produces the following error in vassal.log:

ImportError: No module named site

I believe the origin of this error is that uwsgi is using its built-in Python 2.7 interpreter, while the virtualenv directory it's running in only supports Python 3 interpreters. Indeed, when I use another uwsgi (simply by installing it with pip install uwsgi in the same virtualenv), the error dissappears. However, I'd like one Emperor to rule over several different virtualenvs, so installing a separate uwsgi in each is not an option.

According to this answer on Stackoverflow, The Right Way to solve this is to compile uwsgi with different Python interpreters as loadable modules. Before I commit to this approach, I'd like to know how I can configure my Vassals to each use another interpreter plugin.

Right now I have one Emperor that is started from my /etc/rc.local with the following settings:

[uwsgi]
uid = www-data
gid = www-data
master = true
emperor = /etc/uwsgi/vassals
daemonize = /var/log/uwsgi/emperor.log

Then I have a bunch of Vassals with ini files like this:

[uwsgi]
master = false
single-interpreter = true
socket = /tmp/%n.sock
virtualenv = /home/user/.virtualenvs/djangoproject
chdir = /home/user/djangoproject
wsgi-file = project/wsgi.py
logto = /var/log/uwsgi/%n.log

I have no problem compiling a tweaked version of uwsgi with several interpreter plugins, but I'd like to know what I have to change in my configuration to actually use these separate interpreters. Can I just say one vassal.ini:

plugin = python3.4

and in another:

plugin = python2.7

?

Please help me figure out how to combine Python 2.7 and Python 3 virtualenvs under the same uwsgi Emperor.

Best Answer

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.