
Building Large Flask Apps in the Real World - shinryuu
https://etscrivner.github.io/posts/2014/10/building-large-flask-apps-in-the-real-world/
======
aidos
> In the end you should be aiming to design your application to depend on
> Flask as little as possible.

I'm 3 years in to a project where I've taken the approach of having my "app"
as its own package. Flask is then a thin wrapper that instantiates the app and
then exposes the views to talk to it. I handle validation / sessions / config
etc within Flask.

It's extremely flexible. I have some stuff that runs off as worker processes.
No problem - the core is the same, the wrapper around it is different. I also
have a boot.py that I can call so I'm working directly with the app in ipython
(again, it's a wrapper that starts the app).

I'm currently reworking the structure for capacity planning, which is mostly
just a matter of splitting the Flask app into 2 apps for handling different
parts of the work.

Because my core app is decoupled from the web app it's all really easy to do.

~~~
rahimnathwani
"Flask is then a thin wrapper that instantiates the app and then exposes the
views to talk to it."

Why did you decide to go this way? Is it because the user-facing parts of the
app (the bits where Flask helps) are only a small part?

I mean, if I'm developing a CRUD app with small amounts of supporting non-
interactive code, I can't see a reason not to use Django (and put the other
stuff in manage.py commands).

On the other hand, if I were to write something like an analytics system,
which had a web UI for users to inspect and play with results, I can see that
I'd feel constrained by Django when writing the non-web parts.

As someone who loved getting started with Flask, but then switched to Django
after getting stuck without a good structure, I'd really like to understand
whether the choice of Django vs. Flask should be made based on individual
preferences (comfort of an imposed structure vs. freedom without it) or based
on the type of project (mainly web, or mainly non-web)?

~~~
aidos
Django is fine. And honestly, when I'm starting out I just have a single file
with Flask, a connection to the db and a few routes. If that's all you need,
why complicate your life?

I love SQLAlchemy. Maybe things have changed (I'm a jaded Django 0.96
refugee), but as soon as you take away the Django ORM, you lose the admin and
then all your advantages just sort of fall away. But really, that's my
personal preference with a lot of bias from being there in the early Django
days. I think the Django Rest Framework is absolutely awesome, and it almost
pulled me back to Django but it just took my first morning of screwing around
with some config to remind me of why I prefer the simple frameworks.

And actually, I could already feel with feature creep there. I wanted to have
a remote filestore, so there's a Django plugin for doing it. But a) why is my
framework in charge of how I store the files for my application (that means I
need Django loaded in ipython!) and b) it didn't work quite how I needed and I
could see storm clouds brewing.

In terms of general structure, if you know you're building something bigger,
I'd suggest at least splitting the web bit and everything else as soon as
possible. For me, leaving the web app to handling routing / validation /
marshalling / sessions / templating etc feels like the right abstraction.

I look back on any apps I've built / worked on that a) started off as a CRUD
system and b) are still going and most of them are a mess. Even if they're
clean, the core business logic is mixed up with the standard framework
structure. If you really work at it you can separate things out in the code,
but my feeling is that by starting with an app that doesn't know about the
web, you'll make it much easier to discover where that abstraction lies.

TLDR; use Django if it works for you. Whatever you choose, try to keep the
framework out of your application.

~~~
rahimnathwani
Thanks. Your comments (and whalesalad's) helped make this clearer for me.

A simple (and I think common) situation may illustrate what I took away from
your comments:

\- You create a CRUD app in Django with two types of users: staff (who use the
admin interface to modify anything) and regular (can create/modify their own
data, but only read other people's data)

\- The staff make a mess via the admin interface, so you decide to add some
type of undo thing. You look around for an existing addon that does model
versioning, but people still spend time reverting changes back.

\- You decide you need some business logic (changes going through some
review/approval process) and are scratching your head about how to do that in
Django.

I can see then why "I look back on any apps I've built / worked on that a)
started off as a CRUD system and b) are still going and most of them are a
mess."

------
m_mueller
Here's why I use Flask for every web project:

\- It is both 'out of my way' _and_ flexible enough to scale up. I.e. you can
start with a 5 LOC hello world, but it still handles a large app with lots of
components well (Blueprints).

\- It doesn't force a data model / DB onto me - I can just plug in whatever I
have (unlike Django).

\- It doesn't even force a templating engine onto me - I always use mustache
instead of jinja2 (it's extremely tiny, tidy and portable to any language, so
it's much easier to port code to other devices / platforms).

\- wanna just get started? `sudo pip install Flask && python ./hello.py` -->
served on localhost:5000. I recently started a project[1] while in a meeting
with someone complaining about some complex app we had - built a prototype
with him together that could replace the entire thing _and_ solves problems we
had in 2h. Having a foolproof starting point without any configuration and
then being able to build up from there is essential.

[1]
[https://github.com/muellermichel/guetzli](https://github.com/muellermichel/guetzli)

~~~
waprin
I like Flask a lot, but I take issue with:

> It doesn't force a data model / DB onto me - I can just plug in whatever I
> have (unlike Django).

Django doesn't force a data model onto you anymore than Flask does - nobody is
forcing you to use the Django ORM. Any database code you write for a Flask app
could be re-used in a Django app.

What the Django ORM does do is allow you to write portable apps and
extensions. For example, suppose someone writes an extension for Flask that
uses SQLAlchemy. If I'm writing a Flask app and only have a Mongo database
available, I can't use that extension. On the other hand, if someone uses the
Django ORM to write that extension, as long as I have a Django backend for my
database, I can use their extension. It abstracts away the underlying
datastore. Besides just which database you are using, you can also write a
variety of code that works with Django models. Now granted, this abstraction
can be severely leaky and flawed at times, but it's still quite powerful
overall. Django provides a conventional, standard way to address the issue of
interacting with data in a general way. Again, nobody is forcing you to use
it, because you can just bypass the ORM and write your database code directly.
It's just a powerful paradigm if you do embrace it.

~~~
m_mueller
I agree that you can use Django without the ORM, but IMO it makes it kind of
pointless - what advantage would you get over something more lightweight? The
reason why I'd use Django over Flask is if I want to use at least a few out-
of-the box solutions or extensions, say a standard Admin interface. However,
I'm just the type who prefers building this stuff either myself or using
standard components that are decoupled from everything else as much as
possible. If an underlying framework allows me to build stuff in a tidy and
quick way, that's what I'm going to use. So it's not just about what you _can_
do, it's about how the ecosystem around that tool works.

~~~
waprin
It's obviously to a large degree personal preference, opinionated frameworks
vs microframeworks. The reason why I would still use Django even if I wasn't
using the ORM is because

1) I'm still probably using the ORM. I was just noting that for any data that
the ORM doesn't fit well, you don't have to use it.

2) Why is Flask "lighter weight" than Django? From my perspective, as soon as
you start writing a real app, you end up reinventing all these basic things
like file layout using your own conventions, instead of a standard one that
people are familiar with. The mental burden of figuring out your special
snowflake conventions makes it 'heavier' weight to me. But again, personal
preference :) Flask is obviously much better for really simple stuff, and does
provide a great framework for extensions, even if I still lean towards Django.

~~~
angvp
I think is a myth than Flask is lighter than Django, in my experience I had a
Django app and a Flask app we started with Flask because we believed that
myth, in the end we had an application like 10 times bigger in code, we
refactored in less than a week and the performance was even better for Django
than Flask app. I know this is not a Flask vs Django post, but I woudln't use
something than is almost 3 years ago from the last release and they're
promising a new release from almost a year.

~~~
equalarrow
Correct. I'm working with a flask app now and the tendency was to have a few
files with thousands of lines of code - this encapsulates about 25-30 api
endpoints along with all the necessary imports, etc at the top. Including sql
and the usual suspects.

I think flask is great, like sinatra, for small apps. But I would never
consider it for 'big' apps that represented more than half a dozen api
endpoints and some sort of in-depth feature set.

Above that size, unless it's super simple, you'll pay the price in tech debt.
While our api has worked up until this point, we're gonna scrap it for a Rails
api-only app because we need convention + orm + other things to scale not just
the app, but the team. There probably is a way to do this in flask, but 95% of
our team are Rails guys, so it just makes more sense to go with q company wide
maintainable system vs. what's there now.

For small/single devs working on small projects, flask (and sinatra) are
great.

~~~
m_mueller
I have to wonder - did you try the Flask Blueprint facility? Furthermore you
don't have to use the decorator approach to define the endpoints, there is a
class based initialization (add_url_rule) to which you can just pass a View
class. These are AFAIK the main two ways to modularize Flask code.

------
condescendence
Flask is just awesome, I've never messed with a framework that's made things
so simple yet doesn't take away from functionality if you're looking to build
more complex apps.

Anyone looking to get into webscripting/webapps should definitely take a look
at flask, its python based, good for prototyping or production apps and has
tons of useful documentation.

~~~
samstave
best tutorial starting points?

~~~
siquick
the bible: [http://blog.miguelgrinberg.com/post/the-flask-mega-
tutorial-...](http://blog.miguelgrinberg.com/post/the-flask-mega-tutorial-
part-i-hello-world)

~~~
dewarrn1
Seconded — Miguel's blog is terrific! Major chunks of my (very simple)
website's code bear a suspicious resemblance to his examples.

~~~
condescendence
I think many people's flask personal projects resemble his examples in some
way ;) He covers just about everything a modern web app needs

------
matt_wulfeck
> Scaling in terms concurrent users also has little to do with the web
> framework and more to do with your understanding of load-balancing, caching,
> databases, etc.

This is what it always come down to for me. I know that when we can get our
app running efficiently with reasonable memory requirements on a single core,
then scaling it is really just about launching processes and load balancing
them. Scaling out boxes is always easier than scaling out code -- for better
or worse.

I'm not talking about load balancing servers mind you, but applications on any
given host. Two layers of load balancing. When I'm comfortable with the
resource requirements I launch as little or as many of the app in a
predictable manner across any number of nodes. It's comforting to know that
given X, Y core and ram, I can run N services.

------
esaym
I think Flask is like Ruby Sinatra and Perl Dancer.

I've used Dancer quite a bit. Some for larger apps (30+ pages)

This is how I typically lay out a Dancer app. Starting with a top level
directory of application name, say "MyApp", I put the routes in different
directories instead of jumble them all up in one file. As an example, lets use
an app that handles and tracks customers and orders. So something like this:

    
    
      MyApp/
      └── Routes
        ├── API
        │   ├── Component
        │   │   ├── Customer.pm
        │   │   └── Order.pm
        │   ├── Customer.pm
        │   └── Order.pm
        ├── API.pm
        ├── Customer.pm
        └── Order.pm
    

(templates should have a similar layout in a separate 'Views' directory)

Routes/Customer.pm would handle basic requests like GET /Customer/list and
POST or GET Customer/1

While routes handling json/ajax only requests (from jquery ect) would be in
Routes/API/Customer.pm. Routes/API.pm would be an api for stuff that doesn't
directly involve a Customer or Order object (perhaps returning json from an
inventory table or something)

And if you get tired of requesting json just to convert it into html with
javascript and you want the power of a template (without a SPA); I fetch that
stuff with jquery .load() using the 'Component' routes (dynamic parts of a
webpage). For example, perhaps when making a new quote, you select a specific
customer and you want open orders to be displayed in a popup or inline div
somewhere. Using jquery .load(), you would just easily fetch
/API/Component/Customer/Open-Orders/<cust id#>, ect and then just inline the
returned html. If you stick to a rule of "components can only return html and
not cause a page refresh", you will keep from getting too big of mess with
them.

This is just sorta a method I made from various best practices from other
frameworks. Perhaps its barftastic, but I haven't been complaining about it.

~~~
derefr
This is reminding me strangely of the original, non-single-entry-point style
of writing PHP.

I'm actually kind of surprised that we haven't seen a return to that style,
with more modern sensibilities: each route directly mapping to a file
containing the route's procedure body + any view templates for that route; a
single "common" file at the project root containing dependency-imports and
model declarations, etc.

In the end, it wouldn't actually work like old PHP—you'd still actually have a
single entry-point and all the code would be preloaded rather than loaded into
an ephemeral request context—but you'd be able to _code_ as if the opposite
was true.

Reminds me a bit of the "oldschool sensibilities" of coding with something
like Löve2D, actually.

~~~
agumonkey
Erf, mapping URLs to filesystem path is cute but you lose control.

------
idm
I've used Flask for several dozen projects, mostly in the data science space.
I combined the reusable bits to create [http://flask-
diamond.org](http://flask-diamond.org) \- and I've written lots documentation
to help people get work done using it.

Flask-Diamond establishes some common practices so that you are not starting
from scratch for each and every new Flask app. In a research context, I might
scaffold multiple new apps per month, so this has been a huge time saver for
me. This has also made Flask teamwork much easier.

------
encoderer
The post mentions Falcon at the end. At Cronitor, I rebuilt our ping tracking
endpoint (peaks over 100r/s) with Falcon, breaking it out of Django, and I
wrote a blog post about it: [https://blog.cronitor.io/scaling-django-breaking-
out-not-bre...](https://blog.cronitor.io/scaling-django-breaking-out-not-
breaking-up-c48b4a9e4a96)

Here's a tldr:

    
    
      Logging requests to a flat file on a t2.small instance:
      Django:  519.93 trans/sec
      Falcon: 2083.19 trans/sec

~~~
tedmiston
I'm confused when you say requests are logged to a flat file, but also
requests are sent to SQS (presumably to be processed and eventually hit a
centralized log?)

~~~
mattzito
I think perhaps just to remove SQS as a bottleneck for benchmarking purposes?

~~~
encoderer
Correct, but this could probably be more clear.

------
welder
Flask is awesome! Here are some must-use libraries along with any Flask app:

[https://gist.github.com/alanhamlett/ecb3656a1d1bfb3feb31](https://gist.github.com/alanhamlett/ecb3656a1d1bfb3feb31)
(requirements.txt)

Flask is great for small projects, and also scales to large apps like
[https://wakatime.com](https://wakatime.com)

------
jqm
Falcon ([http://falconframework.org/](http://falconframework.org/) mentioned
at the bottom of the article) does look interesting.

I've also had good experiences with bottle
([http://bottlepy.org/docs/dev/index.html](http://bottlepy.org/docs/dev/index.html))
for building internal apps for companies. The limited amount of users means I
don't have to worry much about scaling and bottle with Paste server works
pretty nicely. Jinja2 templates can also be used with bottle which is a plus.
It's also pretty easy to compile this setup into an executable so it can run
off someone's Windows machine and no need for a separate server. This setup
makes a really convenient internal-use app which is easy to send to end users
for deployment.

~~~
rahimnathwani
If you are bundling as a windows exe, where are you storing persistent
state/data?

(EDIT: fixed autocorrect exe->exercise)

~~~
jqm
Either interact with an external database... (an existing company db for
instance...this is just a front end) or else use a sqlite file on the local
machine for smaller stuff.

------
kunoo
A bit off topic, but does anybody know why development looks stopped since
2013?
[http://flask.pocoo.org/docs/0.10/changelog/](http://flask.pocoo.org/docs/0.10/changelog/)

I'm in the process of writing my first webapp, and thses days it's a bit
strange seeing a popular framework not being updated (even if it's just for
bugfixing) a few times a year.

~~~
matthewowen
It's important to understand that Flask is really, really, really tiny. Most
of the meaningful code about handling requests etc etc etc is in Werkzeug.
Flask is really a small layer adding some convenience functions and tying into
templating.

~~~
pyre
This is very true. I can't count the number of times that I've had to dive
into werkzeug code while trying to figure out how Flask was doing something.

------
TeeWEE
While flask is a nice framework, it has some problems. I worked with numerous
python web frameworks, mainly webapp2 and flask. So some things i don"t like
about flask:

Disclaimer: You can architect beautiful apps in apps, its just easy todo it
wrong.

GLOBALS: Flask has a lot of globals (from flask import g, request,
current_user, etc.) A better web handler function looks like this
handle(request) -> response. Any other web framework that I know does it like
this. Much better. Flask promotes touching the 'request' object everywhere.
Example: [https://github.com/lepture/flask-
wtf/blob/master/flask_wtf/f...](https://github.com/lepture/flask-
wtf/blob/master/flask_wtf/form.py). Flask is not functional, its inherently
statefull with globals.

MIDDLEWARE: Flask promotes writing middleware as decorators functions, while
it looks nice, it not really useable anywhere else, and its not really a
standard. At least you can still use WSGI middleware.

BLUEPRINT are nice, but have issues: When you create a blueprint, for a sub
app, you cant set error handlers. They only work on app level. Also (small
issue) You cant add blueprint specific middleware.

Better way to create 'sub apps': Use a new WSGI App. Or use a sitemap where
you bind functions to paths.

SITEMAP @route has disadvantages For big apps, its nice to have a single
routes.py file where you can see all urls the app supports, and which methods
to handle those. The @route is nice to use initially, but imho for big apps it
becomes messy. Also it promotes circular imports:

    
    
      view.py:
      from init import blueprint #circular import!
      blueprint.route('/test/')
      def f(): pass
    
    
      init.py:
      blueprint = new Blueprint
      from . import view
      assert view # ensure the handlers are initiallized

~~~
irahul
Haven't used flask in some time now, but most of your objections are missing
the mark.

> GLOBALS: Flask has a lot of globals (from flask import g, request,
> current_user, etc.) A better web handler function looks like this
> handle(request) -> response. Any other web framework that I know does it
> like this.

Flask's request is not global. I have had this discussion with someone else
before:

[https://news.ycombinator.com/item?id=6662623](https://news.ycombinator.com/item?id=6662623)

FWIW, flask's "from flask import request" never had been a blocker for me,
whereas django's injected request variable had made me write middleware to
preseve requests as thread locals so that I can access it elsewhere. Werkzeug
does the same thing, except it does it more robustly.

> MIDDLEWARE: Flask promotes writing middleware as decorators functions, while
> it looks nice, it not really useable anywhere else, and its not really a
> standard. At least you can still use WSGI middleware.

I don't see an issue. If you can solve it using simple python(decorators),
solve it using Python.

> BLUEPRINT are nice, but have issues: When you create a blueprint, for a sub
> app, you cant set error handlers. They only work on app level. Also (small
> issue) You cant add blueprint specific middleware.

Rather than calling app.before_request, you can call blueprint.before_request
and it will work only for that blueprint.

> SITEMAP @route has disadvantages For big apps, its nice to have a single
> routes.py file where you can see all urls the app supports, and which
> methods

Then don't use the decorator. Have a routes.py and call app.add_url_rule

I have had a template with all of this from some time back

[https://github.com/rahulkmr/flask-bigapp-
template](https://github.com/rahulkmr/flask-bigapp-template)

------
ccanassa
I spend the last 3 years on the microframework bandwagon, and now I am quite
pleased to be back writing Django code.

In my experience, any sufficiently large Flask project contains an ad hoc,
bug-ridden, slow implementation of half of Django.

------
nerva
So what's a good (clean) way to create the frontend for Flask apps? I have a
decent sized Flask app and I've created a mess with all the templates, static
CSS/JS now.

What JS framework do you tie it to, if you use Flask to just create an
API/manage sessions?

~~~
mslate
I host my Flask API on one server and serve a single page app (Angular) on
another.

The trick with that is having to host them from separate domains and deal with
CORS, however it also allows you to distribute your SPA via CDN instead of
using Flask app servers to serve up that static content. This is what we do at
my full-time gig, but same holds for Flask.

~~~
sandGorgon
I'm just starting out in Javascript development and have been struggling with
build system - how do you achieve cache busting hashes, etc which are
necessary to use for a CDN?

We are using webpack and it seems hard to do it.

~~~
mslate
I highly recommend surge.sh for easy static hosting--their cache-busting
strategy is explained here:

[https://surge.sh/help/using-lucid-caching-
automatically](https://surge.sh/help/using-lucid-caching-automatically)

~~~
sandGorgon
we use cloudfront and nginx for most of our infrastructure - kinda hard to
move to surge right now.

ETags is not viable for this kind of a setup - it pretty much means triggering
a nginx reload which is what a cache-busting signature avoids.

------
nawitus
How do you load balance a Flask application since it's single threaded? For
optimal performance shouldn't there be a single Flask instance (process?) for
each request being processed? What kind of load balancers are usually used
with Flask and how do they decide to spawn new Flask instances?

And why should Flask be used instead of asynchronous Tornado or Node.js?

~~~
Gratsby
I've built with Flask, Tornado, and with Node/Express.

Flask/Python blows Node out of the water where performance is concerned. That
shouldn't be a surprise to anyone.

Flask has a significantly faster ramp up time than Tornado as it is designed
to be simple.

As far as load balancing/performance, you front end it with something like
NginX.

You can process things out of band easily enough with Flask, but I wouldn't
evangelize it so much to say that it's the best solution for every problem.

Personally, I like to keep things as simple and as logically separated as
possible until it's absolutely necessary to change. Flask is one of those
frameworks that doesn't present a lot of mystery.

My biggest problem with node isn't performance - for that it's fine for most
use cases that I deal with. It's that you can get perl-level convoluted and
sloppy very quickly and easily.

~~~
codesushi42
> Flask/Python blows Node out of the water where performance is concerned.
> That shouldn't be a surprise to anyone.

I'm a huge fan of Flask and Python in general, and despise server-side
Javascript (or Javascript anything, really). But I'm curious how you can make
this claim. CPython lacks JIT, and gunicorn + Flask is going to run a process
pool by default, with each process being single threaded and under GIL.

What's your set up then? PyPy and gevent gunicorn workers? Otherwise I don't
see how CPython+Flask+gunicorn could beat Node performance wise out of the
box. At best PyPy + gevent would approximate NodeJS performance, unless you
can tell me otherwise.

~~~
rlander
In my experience, large nodejs apps suffer from linear degradation.

Nodejs performs very well in synthetic benchmarks. In the real world, slow
clients and large queries just kill that initial performance.

~~~
gmmeyer
What do you mean by linear degradation?

------
itajaja
Shamelss plug: We are using flask-resty [1] for our microservices and it's
awesome. it uses sqlalchemy and marshmallow and the resulting code is very
terse and declarative.

[1] [https://github.com/4Catalyzer/flask-
resty](https://github.com/4Catalyzer/flask-resty)

------
abledon
If your interested in websockets for flask, Miguel Grinberg has a
straightforward implementation:

[http://blog.miguelgrinberg.com/post/easy-websockets-with-
fla...](http://blog.miguelgrinberg.com/post/easy-websockets-with-flask-and-
gevent)

------
foxhop
I do not use flask for large applications, I reach for Pyramid instead.

~~~
mkesper
Can you share some advantages you perceive?

~~~
ergo14
Pyramid avoids globals wherever it can, so this leads to cleaner and better
architecture. has an event system that you can plug in, and customizable auth
system. You also have powerful pluggable configuration system where you can
easly add new functionalities to your app as extensions, like provide
pluggable service layer, or auto add new views from external package for your
application that handle some specific functionality.

It was also among first python frameworks that supported py3.

------
avyfain
I have been working with flask over the last 6 months and the deeper I dive
the more I feel like there are 100 ways to do each task.

Can anyone provide a few good open source flask projects worth reading?

------
akoumjian
This was a good general list of things to consider for scaling any web
applications. What I've noticed though is that all my flask apps, after adding
in all of the standard components, eventually converge on a Django-esque setup
anyway. So now I just use Django, and if I don't want to use a particular
component (ie: orm, templates, whatever) I don't, or I swap it out. On the
other hand, if I do want to use those components, they are right there.

~~~
derefr
Do you ever write "apps" that only expose an API, without rendering any HTML?
I find Flask (or Ruby's Sinatra) to be ideal for that case.

Given hexagonal architecture (i.e. your model + business rules existing as a
"service component" library project, that your webapp consumes as a
dependency), if all you need is to expose that service with an API, Flask
and/or Sinatra lets you do so with nothing more than a flat file of 3–6-line
controller stanzas. It's really quite lovely; gets to the core of what it
means for something to be a "microservice."

~~~
akoumjian
I suppose if you already have an existing service component that encapsulates
authentication, authorization, business logic, notifications, and all that
other jazz, then use flask is an excellent way to wrap that to produce an http
api.

------
andrewstuart
Bottle and Flask are similiar and a great place to learn and start your
journey with Python web _application_ development. It is pseudo-minimalist
though, so either you must almost immediately start reinventing the wheel to
build basic stuff that you will need (as a novice developer I started by
writing my own sessions and cookie handler).

The next realisation you'll come to is that all that stuff has already been
written by someone else as addons. So you try that but eventually you'll find
you are in so much pain from problems with integrating addons that you will
realise that you would be best off with something that has all the basic
functionality "batteries included". So then you'll try to find projects on
github that have already baked together Flask plus all the plugins into a
boilerplate project. Then you'll find that there's many ways to bake all that
stuff together and start to wonder if maybe you're now using a framework. But
the boilerplate Flask with addons integration doesn't feel like it has a
really well thought out consistent overarching model.

So you'll then look at full featured integrated frameworks like Django where
it's all integrated according to an architectural vision (perfect or otherwise
is a matter of opinion) and although you might mot like some of the
components, at least its all built in. Flask still carries of cruft and mental
model though, because it is from earlier days of web development when you
built the front end in the back end using things like Jinja templates.

And then one day you'll need to build just a simple REST API without all the
bells and whistles needed in a web application. So you can then look at Falcon
which is extremely minimalist for developer who know they don't want any extra
web application stuff at all including things like back end UI generation with
templates. It's a sharp knife because there's almost nothing in it, and never
attempted to provide the features needed to build user oriented web
applications, so it has a very small mental model to grasp.

TLDR:

 __Bottle and Flask are great for finding your feet in web development without
being forced to learn too many concepts all at the same time.

 __Django or Pyramid or something full featured for web application
development

 __Falcon for REST API development

If you are willing to take on the cognitive load of going straight to your
destination, I would recommend beginners start with Django or Pyramid or
Falcon. If (and this is entirely reasonable) you need to get going in Python
web development without being overwhelmed by the concepts, go to Bottle or
Flask but move on as soon as you can.

If you love Flask and have the skills and competence to craft your own
architecture and carefully selected from a menu of addons that suit you and
know how to whittle out unneeded functionality, then Flask is the right choice
for you.

~~~
wowzer
This is the first I've heard of Falcon. Have you used it for a "real" project?
It'd be interesting to know the tradeoffs when considering it against
something like Django Rest Framework. Looking at the benchmark figures on the
Falcon site, it's sad that Python 3 underperforms Python 2. I wish Python 3
had the slightest performance win, it'd be an easier sell. Hate to shift the
topic to Python 2/3 talks, but I've wanted to switch for a while now, and it's
still not the simplest sell.

~~~
andrewstuart
Yes I have used Falcon extensively and I like it alot.

Lies, damn lies and benchmarks - I'm not saying the benchmarks are made up but
you know - the benchmark thing.

Falcon for REST API development. Django/Pyramid for full featured web
application development.

And regarding speed, well how does its Python 3 performance compare to the
Python 2 performance of other Python web servers? And any does speed matter
that much? In many cases "fast enough is good enough" and the bottle necks are
more likely to be other parts of your system and if speed matter that much
then you should be horizontally scaling.

And if I may raise the ugly topic - who cares about Python 2 under any
circumstances? For me - and I know many people do not think this way - Python
2 is dead so who gives a rats arse anything about it. Python 3 is the future
and I'm not looking back for any gripes or grumbles about it.

Don't get me wrong, I think ruby-rails-slow is a bad thing, but Falcon fast
should be good enough.

And if speed _really_ matters to you then you shouldn't be using Python for
web application development.

~~~
aidos
I looked into Falcon a while back - looked interesting but it wasn't
immediately obvious what I would get over Flask (if nothing else, there's a
tonne of Flask docs out there these days).

In all my research over the years Pyramid is the framework that looks the most
interesting. The docs are amazing (I more or less read them cover to cover,
even though I haven't tried the framework) and the whole thing seems very well
thought out.

I'd love any insights from people who have worked with it.

~~~
goo
I've worked on one project with Pyramid extensively, and I've been relatively
pleased. It gives you a lot of flexibility, which can be good and bad. There
is useful code that helps you unit test your app, and it is not a particularly
opinionated framework. That being said, the number of options that pyramids
allows can be a little overwhelming -- it gets a grade 'C-" when held up to
the zen of python's line: "There should be one-- and preferably only one
--obvious way to do it." When held up to "Although practicality beats
purity.", as well as most of the rest of the pythonic ideals, Pyramids gets a
solid A.

Personally, I'm excited to explore flask more, since it seems to put the ball
entirely in your court. I like the concept behind flask a lot -- for some
projects I'm willing to sacrifice additional framework features in exchange
for a more careful understanding of everything I am adding to my app.

~~~
mmerickel
Yeah I mean it's hard to digest comments like "it's not a particularly
opinionated framework" against things like "put the ball entirely in your
court". They seem to be saying the same thing except you have a different
perception of each when you say it.

The problem as I see it is that Pyramid has a lot of extra interfaces and
support for things in the core by default (and some concepts that are
completely missing from most frameworks like context). So much is there that
it's easy to lose sight of how little is actually required. Fundamentally you
can write Pyramid apps in 10 lines of code exactly as you would with Flask but
that's less interesting for bigger apps and so the docs focus on all the extra
features.

I mean if you take the example at the top of
[http://docs.pylonsproject.org/projects/pyramid/en/latest/](http://docs.pylonsproject.org/projects/pyramid/en/latest/)
and add in the pyramid_jinja2 library via config.include('pyramid_jinja2')
then you basically have views and jinja2 rendering fully baked.

As in the previous example if you get right down to it Pyramid doesn't even
have a templating engine! Flask comes with jinja2 built-in! So scaling DOWN to
APIs where this is not necessary is an interesting thing..

~~~
mayhew
You could always just use Werkzeug directly if you're just building an API.

~~~
mmerickel
"just building an API" does not mean you need something more lightweight. It
means you have different requirements from a standard full stack web
application. You are not dealing with cookies, forms or template rendering but
you are still dealing with lots of other problems including authentication,
authorization, headers, etc. Pyramid is the ONLY framework I've ever seen that
comes with builtin support for dispatching to a view function based on more
than just a request method (GET vs POST). In Pyramid GET vs POST is equivalent
to any other request property including accept headers, cookies, query
strings, etc. Any of these can dictate a different callable. See
[http://blog.delaguardia.com.mx/pyramid-view-configuration-
le...](http://blog.delaguardia.com.mx/pyramid-view-configuration-let-me-count-
the-ways.html) for some examples.

~~~
andrewstuart
That's really useful.

------
m_mueller
Is it really best practice to initialize the logger in each python file? Seems
strange to me, I've always just initialized in the main routine(s) and the
logger that you set up like this is available from everywhere as a singleton
(`import logging ; logging.info("hello world")`).

~~~
pyre
> `import logging ; logging.info("hello world")`

I don't think that this is doing what you think it is doing (assuming that
'import logging' is importing the Python logging package, and not relying on
broken Python 2 package name resolution quirks to import a local module).

The `logging.{LEVEL}` functions always log in the root logger. The loggers
that you initialize have a tree structure. There is a nice package for
inspecting that here:

[https://pypi.python.org/pypi/logging_tree](https://pypi.python.org/pypi/logging_tree)

Several different 3rd party libraries that you might be using will all have
their own loggers that are initialized at their level. By separating things
out like this, you can set different log levels for different loggers. For
example, you might not want Component A logging at DEBUG level, while you want
Component B logging at DEBUG level. This is why one would initialize things
per package like this:

    
    
      import logging
      logger = logging.getLogger(__name__)
    

That logger's log level inherits from it's parent, and the structure mirrors
the structure of your package/module hierarchy, so you can set the log level
for an entire package, or just an individual module. Granted, you may not
require such granularity, but doing this as a standard practice does give you
the flexibility.

~~~
m_mueller
Well yes, but with basic_config I'm telling the root logger in a central
fashion what it's supposed to do - at least that's how I understand it. So far
I've never had the urge to initialize separate child loggers for every
component. Do people do that mainly so you can have fine grained control over
log levels?

~~~
mixmastamyk
Yes, otherwise you can get messages from noisy libraries bubbling up to the
user that may not be relevant in the app context. If the logging is just going
to a file to look at later it matters less, still sometimes it is nice to shut
them up.

~~~
pyre
Examples of libraries that can be noisy:

* Flask-CORS: When I first started using this it's default logging level was really noisy.

* factory (aka Factory Boy): You can turn in DEBUG level to get a _deluge_ of information about what is happening with your test data.

* SQLAlchemy: The 'echo' option to create_engine isn't the only way that you can control logging. E.g.:
    
    
      import logging
      logging.basicConfig()
      logging.getLogger('sqlalchemy.engine').setLevel(logging.INFO)
    

Using logging_tree will give you a good idea of the loggers that have been
initialized on the libraries that you're using.

------
mattbillenstein
+1 flask-classy -- feels a bit like the old pylons which was a very simple and
powerful framework

~~~
bunnybender
The original flask-classy extension hasn't seen updates in two years.

This fork is currently active: [https://github.com/teracyhq/flask-
classy](https://github.com/teracyhq/flask-classy)

------
a_c
The "Architecture The Lost Years" talk is a real gem

------
acidity
Another one that I have used in multiple of my projects:
[https://github.com/mattupstate/overholt](https://github.com/mattupstate/overholt)

------
bkovacev
What do you guys think of webapp2 framework? How does it compare to flask?

~~~
mayhew
Assuming this [1] is the main source repository for webapp2, it hasn't had any
serious development since early 2012 and there's probably no reason to use it.

[1] [https://code.google.com/archive/p/webapp-
improved/source/def...](https://code.google.com/archive/p/webapp-
improved/source/default/commits)

~~~
bkovacev
Yes that is the framework. Well, Google App Engine still suggests using it in
all of their code snippets and is the goto python framework suggested for GAE
apps.

I also probably didn't formulate my question well. I didn't ask whether to use
it or not, but how it compares to Flask - .

------
auvrw
in addition to the flask documentation

[http://flask.pocoo.org/docs/0.10/](http://flask.pocoo.org/docs/0.10/)

the snippets page is really helpful

[http://flask.pocoo.org/snippets/](http://flask.pocoo.org/snippets/)

also, I've some boilerplate

[https://github.com/ransomw/catalog-flask](https://github.com/ransomw/catalog-
flask)

even though it hasn't gotten attn in a while

------
jorgecurio
Don't be fooled by the "micro-framework" line. My experience of building SaaS
on top of Flask is that you are going to have to reinvent the wheels for a lot
of things.

Flask is plagued with abandoned plugins from a cesspool of weekend
contributors which you rely on for basic things such as authentication and
ORM. Tough enough as it is with all the outdated documentation for _each_ of
the plugins you need.

So my recommendation based on 2 years of working with Flask is don't fucking
do it, unless your product doesn't extend beyond couple of HTTP endpoints
served over uwsgi + nginx for your internal applications.

I really wish I'd spent all that time I spent on Flask on Node.js, python was
the wrong medium to distance myself from PHP frameworks.

All in all, 4 years have passed since my search of alternatives to LAMP. And
finally, it wasn't some open source framework or asynchronous javascript to
save the day, it was Amazon Lambda + API Gateway.

Gone are the need to spin up Vagrant, docker, mysql/postgresql. I just upload
the specific script I want and bam. Npm modules and pip modules too.

I've in the process of migrating to AWS and leaving Flask. Great initiative,
ruined by abandonware plugins and modules, certainly not attractive to entice
developers to build their own wheels.

The biggest mistake you could do is basing speed and agility as basis for
going with Flask. It is the complete opposite. I think using Laravel or even
CodeIgniter will significantly cut development time.

Regardless, I'm done with the whole server/client frameworks and have migrated
to AWS without any servers to maintain or setup. There's even frameworks for
"Serverless" architecture now which makes me shake my head.

~~~
orf
Why not try Django? It's documentation is top notch, plenty of maintained
plugins for everything you could need.

Jumping on the lambda bandwagon seems pretty risky, and in any case how does
it protect you against abandonware? To me it's a bit like saying "I don't like
outdated python packages, so I'll switch to nginx instead of Apache!".

~~~
mhurron
> Why not try Django?

They blame Python for issues they perceived with Flask, I doubt they're going
to be too open to Django.

~~~
jorgecurio
that wasn't what I meant, I meant specifically the microframework nature of
Flask means you have to fill in a lot of what other framework gives you fro
free.

I really did wish I was using django and it's a great framework, however, I
would still choose a php based framework over django, my whole point of using
Flask was buying into the "microframework" experience, it hasn't been stellar
nor worth the extra effort.

I do have to say that I rather liked doing things in Flask until it came time
to do the less fun plumbing code that Flask conveniently leaves out for you to
implement and rely on other Flask plugin contributors....it's literally npm
world but far far fewer in volume....I really did not expect using Flask would
become a minefield

About Lambda, yes there is a platform risk, but I don't think it's a huge one
because the code you write on Lambda are largely self sufficient on their own.
At most if AWS Lambda shut down, you'd moving them to a queue based
architecture with EC2 workers chewing away at the queue.

All in all I don't think AWS Lambda is a hugely different than any other
webhosting...I'm more worried that digitalocean is going to sell out and I'm
stuck with dozen of snapshot images that won't work anywhere else.

