support python3 uwsgi apps
Open, Stalled, NormalPublic

valhallasw updated the task description. (Show Details)
valhallasw raised the priority of this task from to Low.
valhallasw added a project: Toolforge.
valhallasw added a subscriber: valhallasw.
Restricted Application added a project: Cloud-Services. · View Herald TranscriptJun 30 2015, 7:19 PM
Restricted Application added a subscriber: Aklapper. · View Herald Transcript
valhallasw changed the task status from Open to Stalled.Jun 30 2015, 7:19 PM
valhallasw added a subscriber: yuvipanda.
ResMar added a subscriber: ResMar.Jun 30 2015, 7:39 PM

Workaround: use lighttpd with fcgi.

pip install flipflop

create ~/www/python/src/app.fcgi:

from flipflop import WSGIServer
from app import app

from flask import request

import time
import logging
from logging import FileHandler
logger = FileHandler('error.log')
app.logger.debug(u"Flask server started " + time.asctime())

def write_access_log(response):
    app.logger.debug(u"%s %s -> %s" % (time.asctime(), request.path, response.status_code))
    return response

if __name__ == '__main__':

(change fc-importer into your tools name)

create ~/.lighttpd.conf:

fastcgi.server += ( "/fc-importer" =>
        "socket" => "/tmp/fc-importer-fcgi.sock",
        "bin-path" => "/data/project/fc-importer/www/python/src/app.fcgi",
        "check-local" => "disable",
        "max-procs" => 1,

url.redirect = ( "^/fc-importer$" => "/fc-importer/" )

debug.log-request-handling = "enable"

(change fc-importer into your tools name)

webservice lighttpd start
valhallasw moved this task from Triage to Backlog on the Toolforge board.Jul 2 2015, 7:09 PM

I've followed the instructions above, and I'm reasonably confident I've done it as described. But when I try to start the webservice, I get this in the logs:

2015-07-28 17:22:23: (log.c.166) server started
2015-07-28 17:22:23: (mod_fastcgi.c.1103) the fastcgi-backend /data/project/movestats/www/python/src/app.fcgi failed to start:
2015-07-28 17:22:23: (mod_fastcgi.c.1107) child exited with status 13 /data/project/movestats/www/python/src/app.fcgi
2015-07-28 17:22:23: (mod_fastcgi.c.1110) If you're trying to run your app as a FastCGI backend, make sure you're using the FastCGI-enabled version.
If this is PHP on Gentoo, add 'fastcgi' to the USE flags.
2015-07-28 17:22:23: (mod_fastcgi.c.1398) [ERROR]: spawning fcgi failed.
2015-07-28 17:22:23: (server.c.1021) Configuration of plugins failed. Going down.

My runs okay standalone.

Have I done something wrong?

I'm at a loss why this would happen. I've changed the app.fcgi to be completely wrapped by a try-except block, and even that fails. That's consistent with the output: 'Flask server started <time>' is not sent to the error log, so it's completely not running the fcgi file. I'm not sure /why/, though :/

@yuvipanda is working on getting the uwsgi option to work, so that would also solve the issue (although I think this points to some underlying issue we don't understand)

Change 227503 had a related patch set uploaded (by Yuvipanda):
toollabs: Add support for uwsgi-plain webservice type

Change 227503 merged by Yuvipanda:
toollabs: Add support for uwsgi-plain webservice type

ok! so if your webservice is of type uwsgi-plain, you can put whatever you want in your uwsgi.ini - that should be able to get you working with python3 / uwsgi with just following uwsgi tutorials someplace. Once we have an incantation that works generally for people I can codify that into uwsgi-python3

GoldenRing added a comment.EditedJul 29 2015, 8:55 AM

Mmmmkay. I've put this in ~/uwsgi.ini:

socket = /tmp/movestats.sock
chdir = /data/project/movestats/www/python/src
pythonpath = /data/project/movestats/www/python/venv
module = app


$ webservice2 uwsgi-plain start

and I get a bunch of these in error.log:

/usr/bin/uwsgi: unrecognized option '--venv'
getopt_long() error

Sorry if this is really obvious, but I can't immediately spot the connection between the error in the log file and what I've put in uwsgi.ini.

On a little more investigation, it seems that --venv does work if --plugin python3 (or --plugin python) is also specified. Putting plugin = python3 in the ini file doesn't change anything. Perhaps adding this to modules/toollabs/files/tool-uwsgi-plain would be a workaround, though not very satisfactory:

if os.path.exists(os.path.expanduser('~/www/python/venv/bin/python2')):
    args += ['--plugin', 'python']

if os.path.exists(os.path.expanduser('~/www/python/venv/bin/python3')):
    args += ['--plugin', 'python']

I guess another option would be this:

from itertools import chain
if os.path.exists(os.path.expanduser('~/uwsgi-plugins')):
    with open(os.path.expanduser('~/uwsgi-plugins')) as f:
        plugins = list(chain.from_iterable([('--plugin', p) for p in f.readlines()]))
        args += plugins

A bit more generic but a bit more black-box as well.

Or, in fact, even just reversing the order in which the --venv and --ini arguments are added to the args list would be good enough. If --ini comes first, then you can specify the plugin in the ini file, and then --venv will work.

I think --venv shouldn't be passed at all by default, and instead should be provided in the .ini file.

Yes, I guess that'd also work!

Change 227690 had a related patch set uploaded (by Merlijn van Deen):
toollabs: uwsgi-plain: remove python specifics

Change 227690 merged by Yuvipanda:
toollabs: uwsgi-plain: remove python specifics

I've updated the wiki with some guidelines on how to get python3 working using this. The biggest problem seems to be that uWSGI mountpoints don't work with Python 3, but that's a uWSGI bug.

Ricordisamoa added a subscriber: bd808.EditedDec 31 2015, 6:28 AM

Thanks to @bd808 and unbit it works!

virtualenv --python=python3 ~/www/python/venv
source ~/www/python/venv/bin/activate
pip install flask
webservice2 uwsgi-plain start
plugin = python3
socket = /data/project/jshint/jshint.sock
chdir = /data/project/jshint/www/python/src
venv = /data/project/jshint/www/python/venv
module = app
callable = app
manage-script-name = true
mount = /jshint=app:app
import sys

from flask import Flask, jsonify

app = Flask(__name__)

def index():
    return jsonify({'I am': sys.version, 'route': '/'})

def test():
    return jsonify({'I am': sys.version, 'route': '/test'})

if __name__ == '__main__':
Ricordisamoa added a comment.EditedDec 31 2015, 6:30 AM

Also routes and static_folder work correctly as shown at and

bd808 added a comment.Feb 22 2016, 5:14 AM

See notes at rOPUPe38255caa48e393cad47092f815f11b3345b98e4#1392953 for a possible fix for tool-uwsgi-python that matches the config used in T104374#1911373.

ResMar removed a subscriber: ResMar.Apr 15 2016, 1:39 PM
Dalba added a subscriber: Dalba.Jul 12 2016, 1:49 PM

Hello! I've more direct and better python3 support in the kubernetes backend - I've written up some docs on :)

yuvipanda raised the priority of this task from Low to Normal.Jul 26 2016, 12:08 AM

Once we migrate all the uwsgi-plain webservice to kubernetes, I think we can call this done *and* remove the uwsgi-plain webservice type.

Once we migrate all the uwsgi-plain webservice to kubernetes, I think we can call this done *and* remove the uwsgi-plain webservice type.

Do you advise tool maintainers to migrate all of them to kubernetes right now?

@Ricordisamoa yes, I do! Can I co-ordinate with you on IRC or email one of these days to move all your uwsgi-plain tools? :) has more info...

@Ricordisamoa yes, I do! Can I co-ordinate with you on IRC or email one of these days to move all your uwsgi-plain tools? :) has more info...

Some of my files live under ~/www/python/src/src instead of ~/www/python/src and I'd love to keep the ability of customizing that with Kubernetes.

Abbe98 added a subscriber: Abbe98.Nov 27 2016, 1:14 AM