Hacker News new | past | comments | ask | show | jobs | submit login
Building Large Flask Apps in the Real World (etscrivner.github.io)
358 points by shinryuu on Feb 17, 2016 | hide | past | web | favorite | 167 comments



> 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.


Honestly this is how all development should be done. Treat the web server as yet another interface into your application to keep it as slim as possible. Need to change web servers, support thrift, avro, etc? Just write another interface that hooks into your application. Easy!

There are plenty of examples in every language where a web framework turns into a web service + caching + session management + ORM + whatever else you can think of then you use all of those features and now you're inflexible, can't easily add new interfaces without seriously rewriting the old and good luck if you need to move away from that web framework for whatever reason.


YES! Your username should be binaryfullofwisdom.


I will take that under advisement :)


"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)?


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.


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."


Hey, original author here.

In regards to your last question, here are my subjective ways of thinking about this. Firstly, I don't think there are many pre-defined or general rules with software development. I've been lucky to work on a pretty diverse set of projects in my career, and I can tell you success or failure almost always boils down to fundamentals not tools - how well do you understand the space you're working in (for web development - how well do you understand databases, caching, concurrency, scaling strategies) and how well do you understand the abstraction tools provided by your language? If your decision making is grounded in these fundamentals, then the tools you choose are not going to make that big an impact. From this point, tool choice is really about economizing the work you'll have to do and managing risk. If you're gonna be building a bunch of CRUD stuff and non-technical users need to view and modify data - then Django and its admin system makes a ton of sense. If, on the other hand, you're developing JSON APIs that you'll be deploying into high-volume conditions that you'll have to react quickly to, you don't want to pin your ability to scale and move quickly on fundamental decisions made in a large underlying library with many unknowns, in this scenario Flask makes a lot of sense because it's not overly prescriptive and plays nicely with almost everything. For this particular project none of us were very familiar with Django, so there were far too many unknowns for us to be comfortable staking a lot on it.


It's tremendously freeing to have your application live as what amounts to vanilla python (or ruby, or php, or clojure, or insert-your-favorite-language-here). Once you've abstracted your core business logic from the HTTP layer, a lot of problems become easier to solve. If you want to replace Flask entirely it becomes very simple. If you want to replace REST entirely with a CQRS-style system, it's much easier. Testing gets easier. Wanna play with your app without firing up a web server? Build it so that you can use it from an ipython shell.

Vanilla is the holy grail. You mention manage.py commands but why not if __name__ == '__main__': do the thing. Or the multitude of tools like invoke (https://github.com/pyinvoke/invoke) and click (http://click.pocoo.org/5/). I digress...

Django is great for a monolith. Stack Django REST Framework on top of it and you're even bigger and nastier. I would never use it again because the amount of time spent bending it to my will often exceeds the time I'd spend building my own system. Fair warning, I have been using Django in production since version 0.96 and have built many companies on it. After ten years of building web apps, using every MVC under the sun, and working with every size/shape team under the sun you really start to appreciate simple things that compose well together. They're easier to reason about. They're easier to replace. They're easier to pull out and turn into a standalone library or shared service. Are you hitting the wall with one tiny part of your app? Replace it with something written in an entirely different language and communicate via JSON, or over a message bus. Not everything can be mapped to a WSGI request/response.

I am so glad aidos has the top comment on this post because his/her style is what we should all be aiming for from the get-go.

I'd definitely suggest reading up on the SOLID –https://en.wikipedia.org/wiki/SOLID_(object-oriented_design) – principles. Furthermore, the adapter concept is often explained with scary Java code samples, but the core of it is wonderful. Essentially you should consider your API as a vanilla system in your language of choice and you build adapters which then allow for external services to communicate. One adapter could be HTTP (via Flask perhaps) for a front-end website. One adapter could be HTTP but one that only speaks JSON, which you might serve under api.yourdomain.com. Another adapter might be via a queue system which allows for arbitrary commands from an external source to get written to a durable queue, so that they can be replayed later.

I took some melatonin so at this point I feel like I am just babbling and about to fall asleep.

tl;dr build things without frameworks, use your language well, be vanilla, compose tiny things to build big things.


I think you are biased to pick a "micro framework" as a starting point. Because of your experience, you have probably seen all the common patterns in building a web app. As a result, you probably have a solution, or know exactly where to look for a solution to any requirement you come across. However, less experienced team would need a lot more guidance and proven best practices to follow. An analogy is a driver in a foreign country. A GPS map might not provide her with the shortest or most enjoyable route, it gets the job done. Django is great for inexperienced team. It's also great for solo consultant.


I feel it's also a lot more about temperament than it is about experience. Some developers prefer to build from scratch and some prefer to maximise reuse.

I fall mostly into the second camp. For non-trivial functionality I will (in order of preference) 1. Find a good existing framework or library 2. Refactor something I've already written to be reusable 3. Develop something specifically for the task at hand.

Even when I plump for 3 I'll be thinking about how it could be made reusable - I just postpone actually putting any effort in that direction on the grounds of YAGNI.


Great points! I've worked with Flask for a while, as I've gotten to be a better developer. I used to have a lot of my logic in the application itself. Now, I ensure my logic lives in its own modules. Flask is really just either a way to serve my templates or API.


This type of development style (http://martinfowler.com/eaaCatalog/serviceLayer.html) is quite well-known in the Java world yet unfortunately people always think that the technique is overkill (in reality, it's really really not overkill, it's only overkill if you force it to be).


Thanks to javax Most things could be switched out easily


I like this approach. How do you handle routes? Do you just initialize a wrapper app that is composed of your own application, wrap your views in Flask views objects and then call `add_url_rule` on them in the wrapper setup code?

If I understand this correctly, how do you define something like a redirect or abort within your own views?


I've tried to explain my structure a bit better in a reply to voltagex_.

For your specific question - all routing is done from within the top / Flask layer (as is redirecting / aborting). My App layer does not have any Flask stuff in, at all, ever.


This is probably a pretty stupid question, but can you point me in the direction of some recommended reading or documentation regarding how i might go about using a web framework as a wrapper for a separate app? I'm just getting started in python web dev, coming from PHP-MVC-framework-land and this idea is fascinating to me but i'm having a hard time conceptualizing how you would do it.

edit: to be clear, i've read Fowler and understand the idea of a multi-layered application i'm just having a hard time understanding how to achieve it technically.


Not a stupid question, especially since I just made it up as I went along - so there's not much to go on. Will try to put together a little mini example on github (but that will require me actually doing a bit of dissecting).

I've also looked through the Fowler stuff (as well as almost everything else on the subject!). One thing I struggled with a lot was how to handle the DB layer. Fowler has that as the layer right in the middle of the system but I really didn't like that model. All the web frameworks are set up so the db layer is very entangled with the framework and it's quite hard to escape.

Let me put something up on github. Send me an email (in my profile) and then I can let you know once I have something to look at.


Maybe I'm just not thinking clearly today but how do you turn Flask into a wrapper? I thought you had to put enough logic in to a class that inherits from Flask to return views and such.


I think I need to explain a bit better. I have a few different layers. From the outside in:

Flask/Web

Deal with sessions, authentication, caching, templating, logging etc here. Fires up an instance of the App and keeps it around for the duration of the life of the Web instance. I actually have an API in here that looks like what you'd expect in most other web apps. It does the validation / error handling etc. In terms of manipluating the data, I'm not a total purist - the API is allowed to load up the SQLA models and make changes. If there's a more complex operation going on though, it will live inside the next layer down.

App

Deal with remote services / data models / db connection. I guess on the outside you might call this a "service layer". A surprisingly large amount of this is data persistance management. The model I use is to put the data access stuff just off to the side at the top level of the app. Nothing in here knows anything about things like web frameworks. This is important. In other places in the system, this same App is used by RQ (worker instances taking on work via a redis queue). There's another web app that uses it for administrative tasks. I can boot it up to work with it in ipython (I do this a lot). Oh, and I don't manage the db life-cycle here. Whichever layer sits above this determines when it's ok to commit transactions. If something goes wrong here we raise app specific expections - the layer above can handle those and relay them as appropriate.

Core

In the very core I have "pure" algorithmic stuff (for context - http://www.countfire.com is effectively an image recognition app). Really this is just one component that the App happens to be using. If the App wants to talk to this, it needs to create the data structures that the core defines. At various borders I often have mappings from the objects in the current local world to versions for the created to talk to the layer below (ps I like namedtuples).

It's a lot more complex than all this, each of these layers has more sub layers etc. And really, what I've called the Core is a sublayer of the App (in my case there's a well definied algorithmic chunk that I think of as the core so it's in its own package - it stands alone as its own library).

There's no real way of knowing where you'll draw lines between the layers when you start but I have a few rules. Any bit of code should be given the bare minimum of data required to do its work. At borders map local data to data for the next layer. Make sure the stuff going into the current layer is really there because it needs to be there. Be a pragmatist - things will change, you'll pull stuff out into submodules. By following the other rules hopefully refactoring won't be too painful.


I'm curious, is this an open-source project? I would love to have a look into how you built this. If not, well, no worries.


No, sorry - it's very much commercial code (it's our startup). Though it's 90% unicorns and dragons :-)

Edit http://www.countfire.com


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


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.


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.


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.


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.


Calling something "lightweight" typically has nothing to do with what you end up having to do with the library to satisfy your specific use case. Flask is lightweight in the sense that it does comparably little and imposes fewer architectural dogmas. It's not lightweight in the sense that it always entails doing less work to get where you want, and I don't think that's how the word is typically used when describing technology. It's the difference between simple and easy -- Flask is perhaps simple rather than the other (when compared to Django).

In terms of utility and productivity, it all depends on what you want to achieve, of course, and I imagine that Django is a better choice in many cases, but when you already have the wheels you feel like you'd need to re-invent, and those wheels aren't the bells and whistles Django already offers I think I'd prefer using Flask.


Gonna have to agree with you. If I remember correctly the overhead is similar between Django and Flask. I love how quickly I can write a hello world app but I find that if I am building any kind of application that requires auth, db interaction, crud like actions, it ends up being easier in the long run to just run with Django.

It may be because I do not use flask enough either. I spent a little over a year working on a production flask app with a small team and I still feel no where closer in solidifying best practices and design patterns with flask.


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.


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.


That's exactly right, it's personal preference. There are people who like some things already thought out for them, and there are people who always build up a mental model of what they want first and for whom it's a burden to then have to map that model to whatever an opinionated framework wants. I think you're more the person who builds the Lego pirate ship with the instructions and then mods stuff to make it more awesome, while I'm rather the person who builds the pirate ship, then gets bored, takes it apart completely and builds something else from the ground up ;-). There's advantages and disadvantages to both modes of doing things.


Agree with m_mueller. I can never wrap my head around how Ruby or Django expects me to think, but I know exactly how I would go about building a 200-route application in flask.


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

When starting with Django the data model is quite inflexible and difficult to work with. Especially the primary key issues.


Check out pyramid. It is more even more 'pay as you go' than flask. And more amenable to extension (ej. Router strategies)


I can imagine there are tools that are even better than Flask for this task in some ways. Just like there are tools better than the Swiss Army knife. The thing is, there has basically never been a situation where Flask has left me wanting more, so for me it's 'good enough', thus if I try anything else it's hard to justify the cost. But for someone who's still searching I'm sure it's a good idea to check it out.


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.


best tutorial starting points?



The official docs http://flask.pocoo.org/docs/0.10/ are also very nice although not full featured and integrated as the mega tutorial.


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


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


> 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.


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.


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.


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


I like Jinja2 templating and haven't fully jumped on the client side generation train. But I'm partially on that train and do do some client side generation. Particularly for elements that need to appear and disappear with the data lurking in the background. What I found is that I can pass json directly to the script portions of a Jinja template and avoid a second request (although certainly subsequent requests are often necessary). It might not be the "right way" but it works for a lot of things and is pretty simple.


I do similar with Mojolicious, but have less of a defined difference between API/JSON routes and HTML routes, having grown the webapp organically for four years or so now. Unfortunately it started as a Mojolicious::Lite app, and the singe routes+logic controller file ballooned to 4k lines (sans templates and copious DBIC modules with custom methods) before I started forcing time to refactor them into separate modules like you've outlined above. I'm about 30% done but the usability (development wise) and maintainability increase is phenomenal.

To be clear, Mojolicious advises a layout like above from the beginning for any serious app (and even provides a utility to automatically convert Mojolicious::Lite apps, for the most part), but when it's in production already and Mojolicious lite makes it a little too easy to put that off when it's so easy to just add another route... Well, I have only myself to blame. :/

I'm really interested in well designed route structures,especially for sites that include both HTML and JSON variants of their data. It's API design any way you look at it, which is always a hard problem, but I haven't come up with general rules that I'm quite happy with yet. Guides or example sites are welcome.


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 - 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.


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...

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


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?)


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


Correct, but this could probably be more clear.


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

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

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


Falcon (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) 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.


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

(EDIT: fixed autocorrect exe->exercise)


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.


A bit off topic, but does anybody know why development looks stopped since 2013? 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.


> A bit off topic, but does anybody know why development looks stopped since 2013?

It did not stop, it just did not get a release. I'm (very slowly unfortunately) in the process of fixing this by restructuring the github org to get trusted contributors to fix this and to make it easier to have multiple smaller releases instead of a huge one. There is always risk in pushing out releases with a lot of changes which is what would happen which is why I want to have people in place that can push releases without my help to fix things if they are regressing.

I would have done it over Christmas already but life keeps happening and this is something I rather not do without having an action plan :)

Very soon now though.


It's a bit unclear how enthused Mitsuhiko remains about Python development. He is one of the greatest contributors to the Python community and undoubtedly one of the most impressive software developers on the Internet. He is very "Python 2" oriented though and I wonder if his enthusiasm for Python has waned because he could never get onboard the Python 3 thing with enthusiasm. To his credit he updated Flask early to Python 3 and he has written alot of other stuff, most of which I understand to be Python 3 compatible.

As everyone here knows, it's hard to write software when you don't feel enthused about the programming language.

He has been doing stuff with Rust in particular. Maybe there will be a "Rusty Flask" one day.


I have done a little Flask work, but can't say that I have really followed Mitsuhiko's work. However, I have been looking at extensively digging into his new python based Lektor CMS

https://github.com/lektor


Apparently his enthusiasm remains high!


There are milestones for 0.11 and 1.0:

https://github.com/mitsuhiko/flask/milestones/0.11 https://github.com/mitsuhiko/flask/milestones/1.0

None of the 0.11 blockers are substantial, and 1.0 is mostly about having updated documentation. It just requires someone to actually finish them.


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.


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.


Werkzeug is also under Mitsuhiko's control and has similar maintenance problems.


It hasn't stopped, there just hasn't been a release. Main issue seems to be that the next release was planned to be the magic "1.0" and that isn't finished. So while that is worked on, there haven't been new releases, because the current release works, and most bug fixes happened in dependencies (jinja, werkzeug). At least that was my takeaway from various github discussions about it.


For more information, the current discussion about a new release is at https://github.com/mitsuhiko/flask/issues/1575#issuecomment-...


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.... 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


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

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


> GLOBALS: .. Flask does not have a lot of globals. You are misunderstanding the g, request current_user object types. They are most certainly not globals, they are session proxy objects. Because we are in python they can be made to look like globals. They are done like this to be convenient. If you use the 'request' one hundred times in a file, some of us don't want to be bothered to put it as a formal parameter to every function.


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.


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?


You could try using Flask-Restless with Backbone-Relational and then integrate with something like React using something like https://github.com/magalhas/backbone-react-component

https://flask-restless.readthedocs.org/en/stable/

http://backbonerelational.org/


On second thought, I'm not sure if a backbone-react mixin is even necessary. You can explicitly subscribe and unsubscribe to events with only a couple lines of code in componentWillMount() and componentWillUnmount().


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.


I used this architecture myself for a while, but I don't think I would implement a new project in terms of it at this point. Given a caching reverse-proxy like CloudFlare, there's no disadvantage in serving your client from the app itself. Meanwhile, you get the advantage of being able to test the server during development by just hitting the single ip:port it's running on—and have your automated testing do the same with subrequests, by using the Host header from the request context—without having to make all your test-harness code "infrastructure-aware", teaching it about ports and figuring out ways to pass them in and route them through Docker and map them to domains instead of ports in production and such.


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.


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

https://surge.sh/help/using-lucid-caching-automatically


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.


You can serve any sort of frontend from Flask. Personally, I prefer Emberjs and have been serving Ember apps from Flask for sometime now. It's as easy as pointing your Flask app's `template_folder` at the compiled frontend folder. If you're using Emberjs, this is the `dist` folder.


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?


Typically, one uses an application server container such as uWSGI for a production deployment of a Flask application.

uWSGI allows for brokering requests across multiple application processes and/or threads, and also allows for more interesting and complex scenarios such as zero-downtime deploys, "automatic" scaling of processes/threads based on load characteristics, to name a few.

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

Tornado's asynchronous request handling is quite nice, but it also forces you to ensure that every 3rd party system you interact with has an equivalent async-compatible library; otherwise you end up blocking a request while waiting for a response, thus defeating the whole purpose of Tornado. Most systems (e.g. Postgresql[1]) have async-compatible drivers, but it's not always the case.

As for why not node.js, well, perhaps a better question would be: How would Node be an improvement over Flask+uwsgi? What are the associated infrastructure/architecture/cultural costs?

1. http://momoko.61924.nl/en/latest/index.html


> "automatic" scaling of processes/threads based on load characteristics

How is this done in detail? In the case of Flask does it create new processes or threads? How quickly does it create a new Flask process/thread to serve a new request?

EDIT: This website documents configuration settings for autoscaling: http://uwsgi-docs.readthedocs.org/en/latest/Cheaper.html - looks like it's based on various heuristics and algorithms, and in practice it's too slow to create a new process for each request, thus wasting resources

I would think that ideally the number of processes/threads would exactly match the number of live requests, otherwise you're either having too few instances to handle all the requests as fast as possible or having too many instances which means that more resources are used than necessary, thus increasing costs.

I think Node.js is an improvement because the architecture is better suited for scaling and all the dependencies are asynchronous by default. Of course, I think there are other reasons for Node.js (e.g. isomorphism, easier full-stack development etc.), but I guess that's another discussion, really.


A count of the flags that you can pass to uWSGI shows 976 different options. It's highly configurable. WSGI itself is a synchronous protocol, but (as icebraining pointed out) uWSGI can be run in async mode [0] which ends up looking much like node.js.

In terms of the ideal number of processes/threads, I'm not so sure number if live visitors is correct. It's going to depend on your various resource constraints but if requests are quick to service there's no problem with having other requests waiting in a queue.

I once was called in to fight a fire where the team said, "we don't understand, we have horizontal scalability, but adding more machines seems to be making things run slower!" - Erm, yeah, because your single db server is on its knees :-)

[0] http://uwsgi-docs.readthedocs.org/en/latest/asyncio.html

Edit to add that I've just looked through the cheaper docs you mentioned and that behaviour all looks pretty sane. You can have a good default number of workers and expand as required. Also, uWSGI forks workers after the app is loaded in memory so you get fast copy-on-write behaviour during worker start.


uWsgi does have an async mode, which works together with an async loop engine like gevent: http://uwsgi-docs.readthedocs.org/en/latest/Async.html

Of course, this doesn't change your app and its dependencies to work in an async-friendly way, but then again, Node.js callbacks are hardly transparent either.


Well, the difference is the entire ecosystem of nodejs is built around async. Fitting it into python is very hard, and you better have a really good reason for trying it. It just doesn't interact favorably with a lot of common python tools (Sqlalchemy being one example)


This. Flask can technically run in an async event loop (see: http://docs.gunicorn.org/en/stable/settings.html). But gevent is a massive monkey-patch on top of Python standard libs to make them async friendly.

If you're hitting enough load where async really matters, just skip Python altogether. And please, please, don't use Node. Just use Golang or Scala for true multithreading, and you'll save yourself the headaches Javascript will bring for something that's not truly parallelized.


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.


Curious about your performance experience with Node - the TechEmpower benchmarks have Node at about 2-4x the speed of Flask:

https://www.techempower.com/benchmarks/#section=data-r11&hw=...

And my experience is generally also that V8 beats the pants off CPython in performance.

I suspect that part of the problem is that the node ecosystem encourages you to just "npm install" whenever you have a problem, and so you have 3-4 layers of third-party libraries doing minimal work (but consuming lots of CPU cycles) on top of your problem space. But if that's the problem - don't do that. Flask is a microframework; it's trivially easy to build a small microframework on top of the Node.js stdlibs. Node was meant as a scriptable high-performance C++ server, after all, and there's nothing stopping you from using it as one.


The benchmark is a little strange.

It has a range of 723 requests (CherryPy) for a plaintext hello world to 6.8Million (ulib) for plaintext. I looked at the Flask numbers and they don't compare with my own - I got between 3 and 4 times that when I benchmarked it myself on hardware that I'm sure was older and less powerful (and I didn't bother to turn off logging).

I looked at the node code and it does not use express - which could very well be the difference I am experiencing.

I'll tell you what though... I'm going to have a look at ulib for static files!


You should compare Flask to Express or Koa, not raw nodejs. Flask is 3x faster than Express and 2x faster than Koa.


The thread-starter's question was asking about Flask vs. Node.js and Tornado, so I answered accordingly.


Followed the link, it shows plaintext from express at 2.1% and flask at 1.3%. Am I missing something?


Flask is on there about 3 times, with different choices for ORM. It's at about 8% when used without an ORM. There's no sans-ORM configuration for Express, though, so still not an apples-to-apples comparison. I suspect the grandparent missed the other Flask configurations in the very long list.


Can you cite your source?


Just follow the link to the Techempower benchmarks on grandparent's post.


> 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.


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.


What do you mean by linear degradation?


I've heard NodeJS is good for io-bound tasks, but lags under cpu-intensive ones. That may explain his results.


Flask actually performs better on CPython than PyPy as of right now


Original post author here. On the single server level I've mostly used Flask behind uWSGI for load balancing, My experience with this has been overall positive (but uwsgi can be a bit of a pain to script deployments for, maybe it's better now though, not sure).

Then there's the further load balancing you can do behind something like an ELB instance in AWS to control load across multiple servers.


I don't know current status, but in the post you would use gevent or similar to async. Also you would put nginx and likely gunicorn in front of the app.

https://www.digitalocean.com/community/tutorials/how-to-serv...


You typically use something like uwsgi or gunicorn to serve requests, and it's uwsgi & gunicorn that decide how many processes or threads to start. These typically sit behind a load balancer and / or a reverse proxy.

In terms of async Tornado / etc, it serves a different need. Like all wsgi servers, it is best to optimize Flask such that you serve a small number of concurrent requests that are fast to prevent a long queue waiting to serve web requests. With Tornado you have more flexibility in that particular area, but also another layer of complexity. Different tools for different use cases.


> Like all wsgi servers, it is best to optimize towards serving a small number of concurrent requests that are fast and end fast to free up the worker pool.

Well, most (or all) web applications I've worked with make database calls to serve a response, which (in case of Flask) locks the whole thread, and there's always the possibility that the database request is slow. That's why I prefer asynchronous web servers where I don't need to worry about this particular problem.

Modern web applications tend to be more like light proxies between the database and other (micro)services. Most logic has been transferred to the client, including templating. Serving static files should be done by Nginx in any case. Therefore I think it's rather critical that the web application does the serving of multiple requests well, and why I think the async architecture is the way going forward.


Well, most (or all) web applications I've worked with make database calls to serve a response, which (in case of Flask) locks the whole thread

I don't get this, when did Flask start connecting to databases? The only point of Flask is that it only provides an HTTP layer, nothing more. If you want to connect to a database, you have to import some other library (or use something from Python's standard library), which may or may not be blocking.


Flask started talking to databases the moment people started using it. It's a web framework. OP's comment was saying it's single threaded nature is a detriment.


Flask is just an HTTP layer, not an execution engine, so it doesn't really have a single- or multi-threaded nature. It's thread-safe, though.

That said, the default development server built-in (which uses werkzeug's underneath) is multi-threaded - just pass threaded=True to app.run(...) - and in production, you can deploy a Flask app using an evented framework like Tornado or Gevent: http://flask.pocoo.org/docs/0.10/deploying/wsgi-standalone/#...


There really isn't a reason, I don't believe, to use Flask over X. It's just as good, and it comes down to your needs.

To answer your first question: you use something like uWSGI. Flask, by default, stores sessions entirely client-side. You'll have to use something like Redis if you want to use more than one server (properly, anyway), but a Python app like this should easily be able to scale. It won't be Flask that stops you, anyway.


A common approach is to run Flask on uWSGI or gunicorn. You then put this behind nginx.


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


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

http://blog.miguelgrinberg.com/post/easy-websockets-with-fla...


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


Can you share some advantages you perceive?


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.


Pyramid also has scaffolds which layout the project in an intelligent way based on some assumptions. Pyramid can be as batteries included or as out of your way as you desire. In the end there isn't a Pyramid way (The Rails Way) there is just Python.

Also the debugtool bar is excellent for tracking down defects.

The last time I check the Pyramid code base had 100% test coverage.

I look to the documentation as a work of art and a standard for all of my opensource libraries.


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?


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.


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."


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.


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.


If your plan is to use Flask and use all the various add-ons to get Django-like levels of functionality out of the box, I think that's a mistake.

I worked on a pretty big Flask codebase (certainly bigger than the one mentioned in the article, though obviously it depends on how you define it, how you structure your codebase, etc). We didn't really use much in terms of third party add-ons, but we did fork and add various useful features, conveniences, etc. I don't personally think the lack of (eg) sessions is very painful, because it's trivial to implement, and there's something to be said for having a code path that you understand. Yes, we spent some time building some pretty generic stuff... but it was a tiny fraction of overall development time, and we gained wins from the fact that we understood our codebase very well thanks to it.

Definitely a balance to be struck, but I really appreciate that the surface area of Flask is small enough that provided you accept the basic conceptual model (request per thread, entry point is a function, etc), you have a lot of freedom to do what you will, and there's very little bias in the system pulling you away from that. Whereas if you don't want to do something the Django way... well, there's some cost to that choice, usually.


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.


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.


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.


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.


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/ 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..


It's a matter of conceptual load, not about the actual capabilities. By "putting the ball in your court" I mean to say that flask adds an insignificant amount of conceptual load, and the overall difficulty to read and understand your app will be based on what you decide to add beyond flask.

By saying "it's not a particularly opinionated framework", I mean to say that it allows you to add, easily, whatever you want to it. However, there is a fair amount of conceptual load in doing so. The difference between a flask app and a pyramid app with pyramid jinja2 built in is that one of them takes about 20 seconds to understand.

Don't get me wrong -- I think pyramid is fantastic. But it it is disingenuous to suggest that there are not differences in complexity between the two frameworks.


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


"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... for some examples.


That's really useful.


Well as one of the primary maintainers of Pyramid I'll just say that it's laughable to me all the comparisons to Django as it's much more similar to Flask. The main difference is that it comes with several more "pay only for what you eat" standardized interfaces that you can use to pull things together. It's declarative security concepts are fantastic and completely missing from most other frameworks as well which choose to punt this part to (usually) half-baked addon libraries built to serve one specific use-case.


>> it wasn't immediately obvious what I would get over Flask

Falcon gives you less than Flask, not more.

For me the big thing is that Falcon has none of the stuff needed for building web apps. Flask has all that stuff cause it was built when back end servers also built the HTML pages. There's alot of stuff associated with that functionality in Flask that is not there in Falcon. It makes it much cleaner.


I think you have that backwards. Python 3 has been dead in the water since it broke backward compatibility. It's slower. It still only has about 20% of Python 2's use. Most active development of software is still in Python 2. There hasn't been a single killer feature of Python 3 to justify breaking compatibility without deprecation. The Py3 Dictator has already had to back down once on "discontinuing" py2 which was supposed to happen in 2015. If he insists on preventing a smooth transition that doesn't require libraries and significant code change then he will just end up with a permanent split as PyPy, Cython or Conda take over Py2 maintenance.


I do not use DOS6 or Windows 3 or OS/2.

I'm interested in the present.

You of course may use whichever software you want but I don't have enough time to learn anything but what is currently being developed.


Most people did not use Windows ME or Windows Vista. Py3 is the ME/Vista of Python. A foisted inconvenience with little benefit. I still haven't heard anyone articulate a benefit other than "it's the future of Python!" Yeah, OK. But it certainly isn't the future of programming in Python until Guido makes an XP or 7.


Noooooo....let's not go there today! :-)

I'd take those benchmarks with a massive pinch of salt. 338µs per request for Flask is the bad case. 0.5ms of the request is spent in the framework, that's not even noise. The fastest framework I've used is one I wrote for coldfusion and that's the only time I've expected all my requests to be sub 100ms. And even then, the network latency turns that into noise.

Look at features before performance - both in the case of frameworks and version of Python to use (Python 3 is a lot nicer).


I just added a comment up-thread with my experience in production with Falcon. Check it out.


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")`).


> `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

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.


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?


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.


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.


Good points. I'll probably switch to the modular way in the next project.


Original post author here. This 100 times, few python programmers realize this, but this is exactly where that bullet point advice comes from.


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


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

This fork is currently active: https://github.com/teracyhq/flask-classy


Well, If you liked pylons - pyramid with classes and matchparam based views will feel also very similar to you.


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


Another one that I have used in multiple of my projects: https://github.com/mattupstate/overholt


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


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...


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 - .


in addition to the flask documentation

http://flask.pocoo.org/docs/0.10/

the snippets page is really helpful

http://flask.pocoo.org/snippets/

also, I've some boilerplate

https://github.com/ransomw/catalog-flask

even though it hasn't gotten attn in a while


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.


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!".


> Why not try Django?

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


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.


With Typescript, node is a decent choice as long as you aren't doing anything fancy on the server. I do a lot of data science stuff and I would literally rather bang my head against a wall violently than use javascript for that.


If thats pretty much all your server does then you can use whatever you like - most of the time I'd want the "hard crunching" stuff tucked away way in another service to call.


Unless your hard crunching needs to be distributed to complete in a timely manner, it is much easier to scale up by having a load balancer distribute users across multiple instances of an app.


I feel like Flask can be ok if your application is simple enough that you can process each request independent of all other requests.

If your requirements are more involved than that, Flask is an obstacle. The way it gives each request its own context makes it hard to have any kind of communication between them, without some kind of "spawn a gevent to wait for a signal" hackery.

Also, Flask comes with Jinja but they should totally be separate. Why should a network protocol layer come with a frontend templating system?


They are separate, Jinja is just a dep of Flask.


The official Flask tutorial includes Jinja2 as an integral part of flask and assumes the user will be using it for all their templating needs.

http://flask.pocoo.org/docs/0.10/tutorial/templates/


> 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.

What Node frameworks are you using?


Express makes Flask look like a heavyweight framework in comparison, and that's by far the most common 0_0




Guidelines | FAQ | Support | API | Security | Lists | Bookmarklet | Legal | Apply to YC | Contact

Search: