Hacker News new | past | comments | ask | show | jobs | submit login
A Beginner’s Introduction to Python Web Frameworks (2018) (stxnext.com)
371 points by rbanffy 30 days ago | hide | past | web | favorite | 162 comments

This is a short list I have compiled a few months ago, FWIW:

    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/

Django is a pretty big omission from your list.

Especially considering Django powers Instagram and Pinterest's backends.

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.

> One important feature Django lacks right now is asyncio support.

Have you looked at Django-channels?

Andrew Godwin is on the job: https://www.youtube.com/watch?v=oMHrDy62kgE

Good point. I was specifically looking for "base-level" frameworks that focus on routing and responses (so are well-suited for API development) rather than full-stack solutions (e.g. FastAPI isn't there either). Just copy/pasted that from my notes -- as I said, FWIW.

Django’s REST library is incredible. Steep learning curve compared to flask etc, but truly an industrial strength library that is brilliantly designed.

I still think WSGI is the main reason for so many frameworks in Python. So probably it will be nice to divide framework or libraries in WSGI and ASGI.

Welcome to php world, 5 years ago, when there where an astonishing number of frameworks. It seems to have coalessed around just a few (maybe the lack of the languague being as hot.. has limited resources)

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.

eg: https://symfony.com/

Not really 5 years ago Python and its framework were cleaner as it is today. They are mostly based on WSGI or ASGI. The only different breed were grand daddy of all framework called Zope and Twisted Matrix (for network programming besides web). Obviously Zope modernized as library with WSGI support and async support is built into Python.

There are a ton of frameworks, but most deployments choose either Django or Flask, unless they have some really specific need (asyncio is one).

Zope is probably the granddaddy of them all. Tried and failed miserably to use it 20 years ago.

Zope was my way into Python, way back in 2000. Brilliant concept, but hard to use well.

The framework I got into Python with was [Webware for Python](https://cito.github.io/w4py/), written in reaction to Zope.

Zope 2 was so ahead of the market when it appeared I had trouble explaining my clients it didn't need a SQL database to persist the data.

I wish it had gotten more attention and care in the past decade.

I saw that gnu.org was using plone, and I couldnt get it working about 15 years ago. But I didn't know python at all then.

Any of those have good Swagger integration?


FastAPI (built on Starlette) essentially generates your OpenAPI docs for free via intuitive use of decorators and type hints/Pydantic models.

+1 for FastAPI. It also has really good documentation

Good howto/tutorial documentation, I had some problems with the reference stuff. For example, finding the places where you have to put some info (attributes, annotations, docstrings) so that it appears in the generated swagger docs (really needed if you want to publish them for external customers).



I'm pretty sure all other popular frameworks have integrations too.

It is extremely easy to integrate Django (well, DRF) with Swagger: https://django-rest-swagger.readthedocs.io/en/latest/

Funny you should ask: https://github.com/berislavlopac/pyotr ;)

Weppy is considered a known older one. That's a sign that I'm getting old.

Is there any python framework that optimizes for developer productivity?

We're talking about Python frameworks, so "all of them". It's not like they're optimized to win req/s competitions or run on embedded nanocontrollers.

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

Django's tagline is "The Web framework for perfectionists with deadlines".

.. That comes with a brief documentation of 1941 pages (as of August 20, 2019)..

That's because it comes with a load of built in functionality.

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

Having extensive docs is a very good thing, much better than having a short readme and then rely on stack overflow to eventually fill in the gaping holes.

It might be a lot of pages, but Django has some of the best documentation out there. Speaking as someone who had to recently use it for a project for the first time, it was very easy for me to find the information I needed in their docs.

Why is that a bad thing?

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.

Isn't there a way to abstract that, using some of Django's libraries ?

Flask is pretty good. Stays out of your way and does what a framework must, and has some extras for forms etc.. if you want to use them. Tornado is fun to use, but less resources and libraries.

I started working with Django when it was pre 1.0 (0.96), as it was explicit in nature compared to Ruby on rails in 2003-4. Subsequently I tried flask and recently async framework. Our team still use flask just for one reason, it's a thin layer over wsgi making it easier and once application or service grows it can disappear completely.

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 traditionally like using the libraries not the Flask integrations (as in your sqlalchemy example) however I do find myself using Flask Admin and Flask-WTForms, since while they do have downsides and you have to commit to using them, they do a lot for you.

I haven't checked out CherryPy, I should next hobby project.

Gunicorn is awesome, uWSGI is also good and feels more "production" to me.

My problem with those additional projects are that I am dependent on one another layer of abstraction and not sure if the team is able to continue to develop it if core developers abandon it. Thats the reason I prefer using libraries, which if not supported can be supported by my team or replaced if necessary.

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

For my apps I'm not worried about abandonment. They are internal applications generally with no access from the web.

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 find Tornado and Falcon really helpful in that manner, particularly when building REST(ful) APIs. Tornado used to be my go-to tool before discovering Starlette.

for just simple api apps I love hug and flask_restfull

Flask, and only Flask.

That seems like a rather extreme statement.

Like any answer here, it's my opinion. If it were not extreme, then it would be not a very strong opinion or worth considering.

Strong opinions should be carefully considered and have compelling reasons behind them. They shouldn't be extreme just for the sake of it.

I say this as someone who happily uses Flask at work.

I don't think Falcon is "old guard". It got stable just about 3 years ago.

Welcome to Hacker News, where anything older than two weeks is utterly obsolete and unusable, unless it’s LISP.

This looks ridiculously like PHP back in what, 2011ish? Kohana, Cake, Zend, etc etc etc. Ultimately they all collapsed into Laravel or Zend.

Well if you will notice all this framework are abstraction over WSGI or ASGI (these are standards in Python Language interface for web programming). So the situation is not same as PHP.

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.

We need to write a lot of small APIs in Python for SPAs. We ended up going with FastAPI which utilizes Starlette under the hood. I'm surprised neither of them are mentioned here.

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.

From what I remember from my research and readings, asyncio based python web servers are _not_ automatically faster than non-asyncio python web servers.

Do frameworks need to be asynchronous or is it good enough to just spawn threads for background tasks?

Asynchronous IO is really good at doing nothing, especially doing multiple nothings in parallel.

async is more beneficial for when code is primarily network bound. WSGI is thread based which comes with a higher overhead for task switching. So it’s just not as efficient for most web server tasks.

Ok I think I get it, but if your backend is say, making a single API call and sending that result back to the user, then there's no advantage to going async since the user has to wait for that network call anyways, right?

Would you use this async then in instances where some of the API calls don't matter to your user?

I don’t know about Starlette/FastAPI, but generally a true async server could still see a benefit, because while that downstream call is blocked waiting on a response, the OS thread can switch to a different request. This is in contrast to a more traditional one-OS-thread-per-request model, where each thread spends the vast majority of its time waiting on I/O. If your work is I/O bound you can use expensive OS threads much more efficiently. Depends on your workload characteristics and requirements.

Python wsgi servers are generally based on processes and not threads since threads would trigger GIL considerations. While your process is making the single API call, the process is not serving anyone else, ergo you can only have so many simultaneous requests in flight as you have workers. Threads have no benefit over asyncio in python due to the GIL and have costs over ascyncio due to setting up the thread context with the OS.

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.

Without going asyncio you can always use greenlets and get the same benefits. Using uwsgi with gevent makes it easy.

I started Python programming 8 or 9 years ago and went from bottle to flask to Falcon to Django to Sanic.

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.

I have used Django a lot for applications where front-end is server generated HTML page with templates. For REST API or GraphQL minimalist framework like CherryPy, flask, bottle and others combined with excellent Python libraries will work great even for a large modular app.

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 started learning Python web-development with Django, but it really didn't click until I learned with Flask and other "minimalist" frameworks first. It could have been the available material at the time, but understanding step by step what I got for "free" with Django was really helpful for me.

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.

Veering a bit off topic here, but I somewhat recently used MJPEG for a "live preview" type of application and found support on the browser side to cause no end of frustration. Details escape me now, but some browsers could never be made to stop streaming without closing the tab, certain versions of Chrome didn't work at all.

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.

Of these frameworks, Pyramid is the only one I know of that uses the concept of traversal. Traversal is an elegant way to tame big projects. Whenever I look at a web framework, I look for traversal and I'm always a little disappointed to see it's missing.

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.

Pyramid is so well designed. The maintainers have a philosophy of "if it's not documented, it's broken", and it shows. They even have an amazing defense-of-design document.


Pyramid is the best of all of these if you don't need async.

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.

Maybe a semi-realistic example would help us understand what you mean by the path segment branch in tree of resources part? Is that like /api/<resource type>/<resource make>/<resource model>/ would boil down to /api/cars/ford/fusion/ with cars, ford, and fusion each being a branch in the tree?

That's right, except that 'api' is probably a resource also. Your app provides a root resource with a __getitem__ method. Pyramid tries `context = root['api']`, then `context = context['cars']`, then `context = context['ford']`, and so on, until it uses up all the path segments or a __getitem__ raises KeyError. Then it looks up the view for the final context and calls it if all the conditions are met for the view configuration.

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.

Why is this better than using mixins when defining a Django CBV?

Class based views: I've got 99 methods and I can't remember the right one.

I started working with Python around 2013 and I still consider Django the best framework to use. Yes Flask you can pick what you want to use but I have found the supporting libraries to be a bit outdated. Everytime I have used it I feel like I am just gluing together a lot of different pieces and it becomes messy. Django is constantly updated and I have little to no worries about security issues.

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's also a myth that Django makes it difficult to pick and choose. For example, this article fails to mention that Django includes support for alternative template engines, including the popular Jinja2. Of course, if you choose not to use a feature like the ORM, you won't get any of the benefits of that feature- but Django doesn't get in your way or make it difficult in any way to do so. You can use as many different ORMs (or no ORM) as you like with Django.

Everything you wrote is true, however I think using another ORM in Django is asking for trouble, or at least it's missing a lot of the benefit of Django. The way models work with admin, forms, etc is to me what makes Django so efficient. Also, you don't get much by switching Django templates to Jinja.

There are efforts in improving that in 3rd party libs such as django-sorcery [1] which attempts to add Django-like ORM experience but with SQLAlchemy and django-rest-witchcraft [2] which is adding DRF integration to SQLAlchemy models. Not everything Django ORM does is supported however a lot of useful functionality works as expected. For example nested resource updates in serializers in DRF works out of the box without needing to write custom logic unlike in vanilla Django ORM DRF. Whats surprising is that the libs dont do too much magic to make it all work and most of it fairly simply plugs into Django so its not as troublesome as people might want to believe to integrate other things in Django. Its actually a pretty nice framework. Anyways for full disclosure Im a contributor to the mentioned libraries so I could be a bit biased here :D

[1] https://pypi.org/project/django-sorcery/ [2] https://pypi.org/project/django-rest-witchcraft/

Thank you. Do you know of any effort to port GeoDjango functionality to other ORMs ? Or is this something Sorcery supports ?

> Also, you don't get much by switching Django templates to Jinja.

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

Bear in mind "crippled" was a deliberate design choice. Templates have a habit of taking over business logic and before you know it you've reinvented old school PHP.

It is a design decision from a time where the general belief was that template designers played in a lower league compared to "real" software developers.

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

A stated reason is:


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.

Sound reasons but there is nothing preventing you to adopt this pattern with Jinja. :-)

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.

Thank you for pointing to the performance improvement, although I never found the templates to be the bottleneck (insert usual suspects here) it's good to know. Since I actually started my journey into python web development with flask+jinja2 and while I found the lack of parameters in Django templates disturbing at first, in practice it never really stopped me (custom template tags and filters...)

I did write a Django project with SQL Alchemy and without any ORM whatsoever.

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.

Thanks for pointing to Starlette, I didn't know it and it looks interesting.

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.

Just curious, what are you using as a payments solution for an e-commerce site in Django? I've yet to find a solid implementation for that, though I guess diving into Saleor and picking out parts of that implementation is the best choice?

We had to integrate the solution of our bank (see https://paiement.systempay.fr/doc/en-EN/form-payment/quick-s...), which was not very complicated since it's basically just a form, a hmac signature and a return URL.

As with Rails, my take is that if you need to make a web app, use the big framework. The pieces you don't use don't cost much in terms of performance or maintainability, but the inverse is true otherwise: piecing together your own Django with a lighter weight framework adds a maintenance overhead that you wouldn't have with a batteries-included framework.

I use Flask for simple APIs and microservices. If I'm writing a full web app, it's Rails (or Django).

Thanks for pointing that out. I agree 100%. Simple APIs and microservices benefit from flask. The moment I need anything like auth though I just jump straight to Django. I don't want to think about it.

We have a legacy Django app at work. Coming from Rails and living in the npm eco-system for the past few years, Django to me seems like an anti-pattern framework in a death-spiral.

Would you mind sharing reasons why you think that?

Its likely to be the application. You can write pretty nice Django or horrendously bad Django. It's MVC - essentially the same patten as Rails.

The post doesn't mention Django's migration system, which is a killer feature. Of course, one should change their database infrequently and deliberately, but it is nonetheless a delight to use, and a feature that is not matched by many other web frameworks, Python-based or otherwise.

> Of course, one should change their database infrequently and deliberately,

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

Flask-migrate for SQLAlchemy (using Alembic) I find every bit as good as the Django migration scheme.

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.

Will chime in and mention aiohttp[1]. It's lightweight, fun, and the API is very user-friendly for those willing to work on a slightly lower level. I use it to build speedy APIs, and coupled with a good ORM (peewee? [2]) it's pretty dope.

1. https://aiohttp.readthedocs.io/en/stable/

2. http://docs.peewee-orm.com/en/latest/

aiohttp is indeed neat. No WSGI (async-based). The API is clean and HTTP-level. Maybe comparable to Falcon in this regard.

Each of my bootstrapped startups were written using Pyramid:

* https://www.remarkbox.com

* https://linkpeek.com

It's pretty powerful. LinkPeek uses MongoDB for storage, and Mako for templates.

Remarkbox uses PostgreSQL with SQLAlchemy, and Jinja2 for templates.

This is a great resource, and there are some neat inclusions like Falcon, but I find the main trouble when building python web apps is deployment. I always feel like I've duct-taped my carefully written app to the web-server.

Why, a Docker container. Yes, even on Windows. Pack up everything into a single image, downloadable from nearly anywhere.

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.

>Yes, even on Windows.

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

Sometimes all you have is a Windows box. You can either run Linux in a VM on it, or use WSL, or run native Windows containers which are a thing. Imagine that you have a binary dependency which is Windows-specific.

Docker on Windows can run linux containers just the same as docker on linux.. it uses a virtualbox vm with linux and runs containers inside that

This is not the case. It uses Hyper-V (which is multitudes faster in every benchmark I’ve seen and much more stable)


And WSL2 takes it a stage further, running linux-native docker on a linux kernel (albeit wsl2 is itself running in a specialised Hyper-V machine).

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.

Not with Home edition, though you'd be ill advised to use that in a production server

If you are using azure. Container service is very good, at least small scale projects.

or you can run on google app engine seamlessly.

I'm mostly fine with Amazon EC2 with uwsgi in emperor mode / nginx / psql

You can very easily deploy WSGI-compatible apps to AWS Lambda in seconds with the open-source library Zappa (https://github.com/Miserlou/Zappa). Zero server maintenance and zero cost if nobody is using your apps (I put up personal apps all the time with this paradigm, it's great). I love it so much I wrote a book about it: https://compellingpython.com/

Where have you deployed? I'm looking to switch for my Django website. I'd like something full-serve like Heroku, but Heroku doesn't work well with sqlite.

If you don't mind a little sysadmin work I've had good experiences with Dokku[1]. I spin up a Digital Ocean droplet or AWS Lightsail instance and it's my own mini Heroku.

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.

[1] http://dokku.viewdocs.io/dokku/

I’ll second this.

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.

I just looked at this myself yesterday and Heroku offers free postgresql instance for under 10K rows. And decided to skip S3-like solutions by embedding my compressed image to the DB[0]. Want 10k-10M rows? That's $9 a month. A bit steep, but easier than configuring DO instances.

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

Depending on what you need and your traffic, a simple $5 Digital Ocean droplet with a nginx reverse proxy in front of Django would do the trick. It'd still let you run sqlite, but Django's pretty powerful when you give it postgres (which you could also run in the droplet).

I have a Flask app deployed on PythonAnywhere that's using sqlite. Not nearly as streamlined as Heroku, but I'm happy with it.

I take that to mean you are hosting your db locally with the app server?

Hardly seems like Heroku is in the wrong there

yes, DB is local on app server. Sqlite is good for my uses. My DB is about 20 MBs. I like to download the sqlite file to my PC to do analysis as the data changes. Postgres seems like overkill and more complicated

AWS Elastic Beanstalk supports Python, and I’ve had a Flask app hosted there for several years now. Two or three easily-fixed gotchas aside, it works great.

Same can be said for any system, regardless of the language.

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.

Say what you want to about PHP, but when it comes to deployment it’s hard to beat.

I have had the opposite experience personally. Any non-trivial application I've deployed has been a lot more complicated with PHP than anything I ever experienced with Python.

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

Yah, I come from a PHP background which is probably why I feel this way about Python... Ruby is likely a similar story since Gunicorn is a fork of Unicorn

Technically the exact same setup can be had with Apache and mod_python. You don’t need WSGI to do python apps.

Only for web apps that don't get much traffic. Constant hand-tuning of PHP-FPM configs isn't fun.

FastAPI is my new favorite python api framework. Pydantic and starlette are such powerful combo.


I was forced to encounter Web2Py in an open-source project several years ago. It was awful. Besides the fact that it's stuck in Python 2 (seriously, even today?), it had a lot of bizarre design decisions. For instance, it loaded controllers by concatenating files in a directory - alphabetically. I know Python's import system can confuse some folks, but surely there was a better way. The whole thing left a very sour taste in my mouth, so I rewrote the application in Flask - unfortunately, the lead developers didn't seem interested in my fork. I've moved far away from their project, but I'm not sure what they're going to do come 2020.

Web2Py is eminently Python 3 compatible these days.

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.

I LOVE Web2py! I use it for pretty much all of my projects. It is the only Python framework that is super easy to use, has enough "batteries included" but not too much, super simple and super powerful templating, decent migrations, simple data access layer not complicated ORM, no import hell, implicit routing.

Developer has a new effort underway that is a little more "pythonic": https://github.com/web2py/py4web

I'm a fan but found it a bit lacking in add ons for new stuff so am learning rails.

> no import hell

What's the problem with import?

Please check your information - web2py has had python 3 support for some time now.

Sour taste and sour grapes? And yes it supports Python 3.

I primarily use Flask for my research project. It was quick to pick up and honestly, I like a more barebones style - one of the reasons I use Sublime Text over IDEs. Plus Miguel Grinberg's tutorial is fantastic at getting you on your feet (though I'm still sour over changes compared to his original tutorial, more because its made it difficult to onboard new developers).

However, Pyramid's made some of the coolest shirts. http://pylonsproject.storenvy.com/collections/56570-all-prod...

For once I thought, you're bluffing, and the shirts were of some Rock band, but it's indeed for the web framework "Pyramid" xD

I met them back in 2015 at PyCon and they said that they loved the art design of Iron Maiden shirts and Eddie, so since it was their product, they decided that'd make it how they wanted

Are any of these extremely good compared to a framework not written in Python? For example compared to Rails or Phoenix?

We’re mainly a C# shop with some JavaScript, but I’ve done my time with php, ror and java, and, Django is still my favourite web-framework. Don’t get me wrong I actually like .Net Core, but DB migrations, authentication, testing and productivity is just better in Django (I do have an unnatural hatred for entity framework). Django even had the best learning resource I’ve ever seen with the testing goat book.

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.

Hating entity framework is not unnatural.

I'm a huge Django fan so Rails has always felt too magical for my taste. Few projects feel more rewarding than writing a Django website, imho.

They are probably not much better as frameworks than Rails or Phoenix but using Python allows you to import a lot of things from the Python ecosystem. (eg http://www.developintelligence.com/blog/python-ecosystem-201...)

Yeah. I asked because I really like Python's libraries in general, but I found Flask to be so-so, and I just recently worked on a large project in Django, which I hated. I was hoping there was some kind of up-and-coming framework in Python I didn't know about.

I'd probably blame the big project rather than the framework. Or maybe the use case was one for which Django is not particularly well-suited. I suggest playing around with the framework a bit until it clicks and then trying again in the future

Apparently Rails and Django are pretty similar. Rails has a bit more magic, and Django is a bit more explicit. (I have only really used Django but was close to choosing Rails and that's what a lot of articles said when I was researching).

Because it's missing from all of these lists and I respect the maintainer a lot I'm going to throw Hug (https://github.com/hugapi/hug) into the mix.

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.

For such a comprehensive list, no mention of tornado?

That surprised me too. IMHO Tornado should be #3 after Django and Flask since AFAIK it has the best built-in support for writing hybrid HTTP/WebSocket servers in Python.

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.

+1 For Tornado.

I'm curious if you care for their templates or not, though.

Sorry, I haven't used Tornado's templates enough to compare them with e.g. Django's.

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.

Yeah. It's odd. We use Tornado for all our API/microservices at work and it's been a pleasure. More and more libraries are getting asyncio support as well and they integrate well with Tornado.

Is Tornado still relevant if you can use async for multiplexed IO?

I've been using Tornado for coming on 6 years. It's a great example of a solid, well maintained project. Why it's not more popular I'll never know.

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

Fun fact: Tornado was created by FriendFeed, a completely unmemorable social "aggregator" that was gobbled up by Facebook during the social media craze.

Beginner's guide to choose a Python web framework: Django.

Don't know why this is downvoted - it's crystal clear advice for beginners - "just use Django".

Django brings a lot of concepts with it. It may be simpler to start teaching with Flask and build up from there until the need for something like Django becomes obvious.

Right. With Flask, I can simply get to the point where I'm rendering templates, styling with CSS, adding assets and populating template variables with data from simple (or complex) functions I've written.

You can take care of a lot with just that.

Eventually, when the application reaches production, you'll have cobbled together a unique subset of Django.

That's the downside of Flask.

And good luck with auditing upstream versions and security in general.

Django projects can be extremely simple.

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.

Flask has a very dedicated fanbase.

There seem to be some people who just have a problem with Django choosing sensible defaults for average scale projects.

I know some may not consider the category as part of web frameworks, but one significant omission is the category of static site generators (e.g. Pelican).

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.

Japronto looks promising but the lack of community support is discouraging. Another alternate could be Sanic if you are going to use Python 3.5+. Support for asyncio is essential if you want to serve a million requests per sec.

I love using webapp2 on Google App Engine. Using objects and inheritance for request handlers really clicks for me, in a way that Flask’s decorators and magic imports never does.

Anyone have any experience with getting an ioc container going in your python project? What route did you go?

Applications are open for YC Winter 2020

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