Flask-standalone to WSGI-app

Photo by Chris Ried on Unsplash

I like to start my flask projects with a simple __name__ == "__main__" with argparse and app.run(). But obviously the flask inbuilt server is not the fastest and probably not the safest either. This is why you should eventually use a WSGI-runner like waitress to run your app. This post will show how to migrate, while keeping any standalone capabilities.

Migrating “__init__” code

In short, everything in your if __name__ block is not going to be executed anymore, the simplest solution is to move it to a @app.before_first_request anotated function, so:

app = Flask("LOL")

if __init__ == "__name__":
# arparse stuff
# init stuff
app.run(host="", port=5300)


app = Flask("LOL")

def doStuff():
# init stuff

if __init__ == "__name__":
# arparse stuff
# write arparse results to config
app.run(host="", port=5300)

Obviously, we now need to create an alternative option for configuration to argparse, whenever the app is started through WSGI. This means we must write any argparse-inputs, which aren’t port or interface, to a static config file. You can, for example, create a config.py in the root directory of your project and load it with app.config.from_object or you can simply use:

app.config['OPTION'] = "something"

We can then change it like a namespace-object (basically a dict-object). Remember that any options you pass to app.run don’t have to be/can’t be written to app.config, as they will later be supplied by the WSGI-runner configuration.




app = Flask("LOL")
app.config.from_object("config") # note the missing '.py'
app.config["MORE_OPTIONS"] = "Hello"

def doStuff():

if __init__ == "__name__":

parser = argparse.ArgumentParser()
args = parse.parse_args()

app.config['SOME_OPTION'] = args.SOME_OPTIONS
app.run(host="", port=53000)

Finally you need to add an entry point. The simplest way to do this, is to create a new file and add a really simple function, which returns the flask application in your main module, e.g. the following app.py with ‘app’ being the global variable app in server.py, aka your main file, presumably containing all the annotated functions/webserver paths etc. :

# note the missing'.py'
import server as moduleContainingApp
# default value is required
def createApp(envivorment=None, start_response=None):
return moduleContainingApp.app

You could also use the environment for on the fly configuration.

Setting up WSGI (waitress)

The simplest production server for the WSGI-protocol is waitress, you can install it with pip, or via apt as python3-waitress on Debian9+. Then run it with:

waitress-serve --host --port 5300 --call 'app:createApp'

createApp is your entry point, app your app.py containing this entry point.

Bonus: Running with systemd

Write this to a file called NAME.service in /etc/systemd/user/

Description=Hello Flask

ExecStart=/usr/bin/waitress-serve/ --host --port 5004 --call 'app:createApp'


Enable it with it’s full path, then start it by it’s name:

systemctl enable /etc/systemd/user/NAME.service
systemctl start NAME

Now it will run and start automatically on reboot. No more excuses to use cron-@reboot. You people annoy me. Yes I’m looking at you.

Example Commits

Below are some of the commits, which implemented this transition:

Feel free to share your thoughts or ask a question!




Python programmer at heart, Linux Expert at work, GameDev on my good days, web developer on the bad days.

Love podcasts or audiobooks? Learn on the go with our new app.

Recommended from Medium

Introducing Axiom — Data Solved

Data Structures and Algorithms

Crio Winter Of Doing — My Learning Experience till now

Flutter in Mobile App Development — Pros & Cons for App Owners

How to Get Gatsby to Work with Drupal: Building a Gatsby Site with a Decoupled Drupal Back-End

Hands-On Canary Deployments with Istio and Kubernetes

Django Rest Framework for backend

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
Yannik Schmidt

Yannik Schmidt

Python programmer at heart, Linux Expert at work, GameDev on my good days, web developer on the bad days.

More from Medium

How to send DHT data from ESP8266 to Arduino IoT Cloud

Python vs Other Programming Languages.

How I Made an Automatic B’day Wisher Using Python

An informal introduction to Python