A Beginner’s Introduction to Python Web Frameworks (2018)
stxnext.com
stxnext.com
New kids on the block:
- Starlette https://www.starlette.io
- Vibora https://vibora.io
- Xweb https://github.com/gaojiuli/xweb
- Storm https://github.com/jiajunhuang/storm
- Responder http://python-responder.org
- Quart https://pgjones.gitlab.io/quart/
- Sanic https://sanic.readthedocs.io
- Bocadillo https://bocadilloproject.github.io/
- Japronto https://github.com/squeaky-pl/japronto
The old guard:
- Flask http://flask.pocoo.org
- Tornado http://www.tornadoweb.org
- Falcon https://falconframework.org/
- Bottle https://bottlepy.org
- Pyramid https://trypyramid.com/
- CherryPy https://cherrypy.org/
Less known older ones:
- Wheezy Web https://pythonhosted.org/wheezy.web/
- API Hour https://pythonhosted.org/api_hour/
- Morepath https://morepath.readthedocs.io/en/latest/toc.html
- Klein https://github.com/twisted/klein
- Weppy http://weppy.org/At some point, Python's creator Guido van Rossum also said "My personal favorite -- and I expect that that will remain a personal favorite for a long time -- is something named Django. ... I highly recommend it."
Personally, I use Django with REST Framework (https://www.django-rest-framework.org). I've enjoyed using it tremendously for the past few years.
One important feature Django lacks right now is asyncio support. There are plans to add it though (https://groups.google.com/forum/#!topic/django-developers/Kw...). Hopefully that happens soon.
Have you looked at Django-channels?
https://github.com/ergo/pyramid_apispec
I'm pretty sure all other popular frameworks have integrations too.
I wish it had gotten more attention and care in the past decade.
So it has right level of abstraction making it between a library and framework and you can use it either as library or framework. The difference is "framwwork calls your code" and "your code calls library code". I like the second paradigm more.
In order to make job very easy to develop there are excellent libraries so I have used flask, sqlalchemy (direct no flasl-sqlalchemy), alembic, marshmallow, celery, machine learning libraries (sci-kit, tensorflow, keras) and few more.
For development use cherrypy to graft wsgi app and for production use gunicorn or uwsgi. Our team is extremely happy and our test coverage is 98% as we use code as libraries not asnframework, so it makes it easy to test rest API and celery task code.
Also when needed for performance (not often as most libraries are better tested and designed), did take away the library abstraction and write our own code.
I haven't checked out CherryPy, I should next hobby project.
Gunicorn is awesome, uWSGI is also good and feels more "production" to me.
We use Flask mostly for REST API, so flask-admin and WTForms do not add that much value as all those are done on client side SPA (I do not like SPA, but it makes job easier as same API is leveraged for integration and mobile app).
Also the code is solid enough where I feel I could maintain it if I needed to, but most likely it would get picked up by someone else.
I say this as someone who happily uses Flask at work.
I am sure Flasks documentation is a lot smaller but its essentially just a few parts of Django (it doesn't have a built in ORM from what I understand). Start adding in the documentation for SQL alchemy, documentation for an authentication library and whatever else you need and you will probably start getting something similar but without the guarantee that the pieces will play nicely together.
(Djangos documentation is really good.)
It's got wide feature coverage and excellent documentation.
I think maybe you're insinuating it's overly complex or hard to learn in which case come out and say that so we can engage with a specific assertion.
"Developer productivity" is so vague, I'd regard it as weasely if it would be in a framework's description.
What's the developers aim and workflow? Depending on that, you can probably make an argument for most frameworks on the list.
- Django is your all-batteries included framework for standard CRUD with an integrated admin interface. For "average" jobs that feeds the productivity.
- But then you can make the argument that this approach gets in the way if you deviate from the norm, and Flask is the new productive toy.
- And isn't all the hubbub about a "pythonic" style getting in the way? Web2Py has some magic that might not be mainstream, but is just bound to ramp up productivity! (No experience myself, just using this for the argument and for nostalgia when every mention of it brought the main developer in the thread, arguing about this, just like redux today)
- But hey, man, we're all doing JS frontends and just need a web scale API. Erm, okay, then Django Rest Framework? The various Flask addons? FastAPI?
- I'm an ex-00s-Java developer who misses writing XML by hand. What's best for my productivity? Well, what about the endless joys of writing YAML by hand! Use connexion...
Salt this discussion with complaints about speed (charge of the Rust brigade), deployment hassles (Gophers emerge from the ground) and the collective "this isn't static and thus we're doooomed!" outcries (erm, Haskell?).
(And from the Waldorf & Statler balcony, enterprise programmers who get paid by the hour, laughing about "productivity")
Where php ended up somewhat confusingly is the frameworks are now frameworks and components to make web programming easier (syfony/zend...), which seem to be driving drupal and wordpress development.
Moreover if you look at the framework code of many of them you can replace them easily, for example Flask and bottle.py can be completely replaced by your own code if your service or app grows the intended performance. The lowest common denominator in both is WSGI.
Django is incredible - I wish I'd started with it. It's truly the most useful framework I've ever used - a real workhorse for building applications.
Flask and bottle are minimalist and get the job done for focused tasks - for example I hacked together various web examples into an mjpeg server recently used Flask (based on Miguel Grinberg's webcam server). You can get a simple web site up and running in 3 minutes with bottle or Flask. I'd recommend against using them for anything bigger though - you'll just spend all your time reinventing Django (badly).
I use Sanic for asynchronous web servers.
Falcon is great to use to build APIs - it's raw and minimal and built to task.
Indeed in my latest project I use Django for the main web application, Flask for the mjpeg server and sanic as a long polling web server acting as a message queue server.
It is not true when you recommend don't use flask or bottle for large apps. On the contrary it will be good for large projects to use minimalist framework as they will act more like library. Also you can write code yourself for the parts in the system which outgrow the framework. My team has built large production level application for machine learning service initially in Django and then later ported completely to flask. Given we don't use templates and jinja2 as most of the front-end is in SPA, flask has been wonderful to work with. Django rest framework doesn't work that well when you just need to work directly with request/responses. Blueprints made it so easy to write large modular code that choice between monolith and micro-service, just a configuration setting coupled with either gunicorn or uwsgi in emperor mode.
All Python framework under the hood are WSGI or ASGI, so a decent Python programmer can use excellent marshmallow, sqlalchemy, alembic, celery and flask (or others) with blueprints to write a performant large modular application and a service layer.
I think it also helped me understand web frameworks (or at least the specific paradigm) in general. At times with learning Django I felt like I was _learning Django_. I have this same issue with ORMs.
That said I still really like Django and use it now that I have a somewhat better understanding of what it's actually doing.
It felt great to finally figure out the correct HTTP header incantations to get a working-ish solution with MJPEG... but if I had time to revisit it I would have tried instead encapsulating JPEG frames in WebSocket messages and blitting them to a canvas with JS.
MJPEG seems to be firmly in legacy territory and while browser vendors have to keep supporting it for IP cams, it's probably going to keep getting hit with the regression stick. Meanwhile WebRTC is notionally the correct replacement technology but the complexity is high and support is still hit or miss.
Starlette was developed by the same dev who wrote the Django RESTful package. If you mostly just need REST APIs or even GraphQL, it feels far more light and modern than anything in Django and forms some better opinions around things than the usual roll your own stack in flask alternative. Not to mention it's ASGI based instead of WSGI and naturally faster because of it.
FastAPI just builds on that by adding some nice features like minimal dependency injection and really awesome integration with type hints via Pydantic.
Would you use this async then in instances where some of the API calls don't matter to your user?
With asyncio based implementations, while the coroutine is waiting for the response on the API call, the process's event loop can check on the coroutine which is handling the network socket and start processing another request. Ideally it should have no impact on the amount of time the original request takes to process but you can see how it might since when the API call resolves, the process may be working on the other request instead of continuing with the original coroutine.
Asynchronous code in general can allow you to extend your bandwidth past the number of concurrent executions your program can maintain (whether they be processes in python or threads in other languages) by doing additional work while it is waiting for something to complete. Ideally it should not cost much in terms of latency.
Traversal means the framework treats each path segment in the URL as a possible branch in a tree of resources provided by the app. After completing traversal, the framework looks up a context-dependent view and checks a contextual access control list before calling the view. It feels right to declare security restrictions and other conditions outside the view.
http://docs.pylonsproject.org/projects/pyramid/en/latest/des...
Look at, for example, the best of all the flask tutorials of all time, Miguel Greenberg. He still has to create a ton of the boilerplate and then restructure the app half way through.
Pyramid is the goldilocks of frameworks: Just enough to get you going without insanity, and not too much to bog you down.
Here's the real truth: If you're going to build anything nontrivial, you need a ton of stuff that Flask doesn't give you, and the packages that are easy to install and add to your project are mostly anti-pattern.
If you are going to build something nontrivial with Django, you're going to have to tear out large parts of it and redo stuff.
Pyramid is the best balance. The WebSauna team si doing some amazing stuff, and I'm working on something similar that's a little more lightweight. Pyramid is a very active ecosystem. Just a little less exciting because we have some conceptual relationships with Pylons.
If you need async or websockets, I use starlette/fast-api for endpoints that get hit from my mako templates.
That's traversal in a nutshell. Resources can be database objects or any object with a __getitem__ method. Everything about traversal is customizable, but it's rare to need much customization.
Also, if your resources have __parent__ and __name__ attributes, you can ask Pyramid to generate the URL of any resource and view using `request.resource_url(resource, view_name)`, which is really handy for ensuring URLs don't break.
Edit: And I have been following new projects such as starlette which I have really enjoyed but I have not bought into the idea of why I need async database access.
It made sense because it was database-heavy and UI-light.
Yes, you have to do a bit more when producing forms. You have to do it anyway if your DB operations are not simple CRUD.
Sure you lose much of admin stuff, too.
Django is a framework, a structure where you add (preferably small) pieces of your code to customize its behavior. If what you are building deviates seriously from what the framework was intended for, it quickly becomes more of nuisance than help. But within its subject area, a framework is highly efficient.
[1] https://pypi.org/project/django-sorcery/ [2] https://pypi.org/project/django-rest-witchcraft/
Well, you gain a lot of performance - as much as 10x depending on the complexity of your template. Also, Jinja is a lot less crippled than Django Templates (for example, you can't call a function/method with parameters in Django Templates).
It is 2019 and personally I see no reason to think professional template designers will shoot themselves in the foot if we give them too much power. We are all consenting adults...
https://django-best-practices.readthedocs.io/en/latest/appli...
A common pattern in MVC-style programming is to build thick/fat models and thin controllers. For Django this translates to building models with lots of small methods attached to them and views which use those methods to keep their logic as minimal as possible. There are lots of benefits to this approach.
DRY: Rather than repeating the same logic in multiple views, it is defined once on the model.
Testable: Breaking up logic into small methods on the model makes your code easier to unit test.
I'm glad that Jinja2 templates are now first-class citizens in Django as I care about performance and don't feel like patronizing template designers with a carefully handicapped template language.
I completely agree with you on Django. I've had the chance to implement an e-commerce solution in Flask and another one in Django and the process has been a lot easier and faster with Django. You just can't beat having all the basic tools bundled and configured, along with one central documentation.
I use Flask for simple APIs and microservices. If I'm writing a full web app, it's Rails (or Django).
I'm not familiar with frameworks other than these two, but I bet Alembic works well in most cases if they don't have something already.
I think this attitude leads to a lot of crappy code. It's "safer" just to add a bit more to the application layer than to change the database, but do that enough times and you end up with a mess to compensate for a database design that doesn't model what it needs to. (Learned through experience).
It's pretty powerful. LinkPeek uses MongoDB for storage, and Mako for templates.
Remarkbox uses PostgreSQL with SQLAlchemy, and Jinja2 for templates.
It's great for side projects without the limitations of Heroku's free tier. Lots of plugins (Postgres S3 backups, Lets Encrypt certificates) are icing on the cake.
I work on a selection of internal applications and services and we run everything with Dokku. I was skeptical at first because it made initial [legacy code] deployments a bit of a pain, but I’ve been converted. Not sure I’d run everything that way but for small-scale applications it’s a breeze. And because you have to do the sysadmin work yourself it’s a bit more flexible than Heroku.
Hardly seems like Heroku is in the wrong there
[0]: I know this is not best practice, but this is a small project and this is a hack that I fully know the tradeoffs for.
Unless you’re able to create an artifact like a single executable or a Jar but you still need to supervise those and keep them running.
Asyncio really makes a difference here. I also hate that PHP has to spin up with every single request. This is something I have never gotten used to (From my understanding, most Python web frameworks just give you a clear/fresh Request Object, which is so much better even with WSGI (unless you're using WSGI scripts) Much easier to maintain application state this way in my experience. PHP-FPM doesn't exactly solve this problem, I don't think).
Your web server (which likely also terminates TLS) has to have fastcgi support, you configure the fastcgi and database ports, maybe mount a directory with config files into the container, and that's it.
This would require you to run your containers on Windows servers right? Not much reason to do that anymore.
Instead should just containerize as part of deployment pipeline
I haven't used Docker with WSL2 yet, but in other uses I've found WSL2 extremely fast. As long as you stay within its vhd, file access is ext4-quick. And on my machine running the geekbench cli gave me almost identical results to a native linux install.
Developer has a new effort underway that is a little more "pythonic": https://github.com/web2py/py4web
What's the problem with import?
I have used it for largish projects, and consider it very much not awful at all, but I am aware of opinions on the subject often being polarised (Flask creator Armin Ronacher for one has spent a lot of words and energy badmouthing Web2Py - a behaviour I personally find somewhat unbecoming).
For those not caught up in dogma too much: Try it. Got a lot going for it, and the docs are superb.
However, Pyramid's made some of the coolest shirts. http://pylonsproject.storenvy.com/collections/56570-all-prod...
That being said, the job market for Django is non-existent in my area, and most of my country, and that’s a rather vital issue.
Really easy to build fast, versioned, testable, documented, async APIs with Hug. If you're making a quick project would highly recommend giving it a spin.
You can take care of a lot with just that.
That's the downside of Flask.
And most of the "concepts" Django brings with it are extremely important for any non-trivial web application.
Django also makes it harder to mishandle security.
There seem to be some people who just have a problem with Django choosing sensible defaults for average scale projects.
Yes it's still relevant because your framework needs to be able to run on the asyncio event loop (a feature which Tornado added early on).
I use Tornado to serve the WebSocket backend for https://www.slickdns.com/live/. I've also used Django Channels to add WebSocket support to a Django app and found it very cumbersome compared to Tornado.
I'm curious if you care for their templates or not, though.
Essentially all I use Tornado for is to publish a WebSocket endpoint, and for that specific purpose it's great. For building conventional web apps I'm very happy with Django and its templates.
If you want a fairly simple site that you'll use/modify only occasionally (e.g. blog), save yourself some headaches and just use something like Pelican. No need to worry about databases, and no need to worry about how to deploy. I used Django for some years, but the hosting provider kept making changes to the libraries resulting in my web site going down frequently.