Python web micro-framework battle
slideshare.net
slideshare.net
That said, really the only valid point here against Flask is Python 3 support. Other than that Bottle and Flask are pretty much on par with each other.
Will come eventually. Right now the topic comes rarely up and it requires a ton of work on the Werkzeug side to make it work in a way that is user friendly. That being said, Flask and Jinja2 are not the problem here. The former easily works on Python 3 and the latter already does (just that we don't have any users on Python 3 yet).
Aside from Python3 Support (which is a bit irrelevant at this point), what does Bottle actually offer that Flask does not?
Nothing, that I can see. Flask has a thriving community, first-class extensions, extremely high quality documentation, and an elegant API. It even lets you dip down into the lower-level werkzeug when you want.
Is Bottle being chosen because of LOC? Again, completely irrelevant.
https://bitbucket.org/mdg/cohpy-hips-presentation/src/89b3d2...
shrug
For me, it's all about fitness for purpose. In the end, the prototype consisted of four files (Bottle, Rocket, the Service wrapper and my code) with no other dependencies. Made it a lot easier for the overworked Windows admins to deploy. Flask was completely unsuitable for that.
- "saddled with any dependency baggage" == "has no dependencies"
- "beating on Flask" == "using Flask"
- "shrug" == "i didn't spend a lot of time on this"
- "Flask was completely unsuitable for that" == "I was unwilling to ask for help from the people who use Flask"
Additionally, Flask is also "easy to understand" and has "sane defaults", and it doesn't "require any boilerplate code" either. The context of the comment makes it seem like it's subpar on these things.
I'm all for people pointing out fitness of purpose for various frameworks, but this comment might have been better phrased as "I use Windows. I happened to find a recipe that let me run Bottle as a Windows service. That made it easier for me to use Bottle. Also, I like being able to deploy without the use of packaging tools."
Would you expand on what you meant by:
> The context of the comment makes it seem like it's subpar on these things.
What I intended to get across was that Bottle, being a single file at ~2700 lines, makes it convenient to scan the code to see exactly what it is doing (or not). It also doesn't require a lot of typing to wire a function to a URL and offers some nice syntactic sugar while doing so: you don't have to @route things you can @get them or @post them (it's probably my Java background that makes me think in terms of separate code paths for the different HTTP verbs).
My take on a more detailed (and hopefully hyperbole-free) summation of my original post is:
"Because this was a short timeframe prototype, they had no Linux VM available in the lab so I had to use Windows. I found a recipe that let me run Python stuff as a service which I was able to wrap around Bottle more quickly than I was able to with the other frameworks I tried. Because I was working on a machine that had no access out to the internet, I had no virtualenv and had to instead bundle all my stuff up by hand."
FWIW, there's a Flask-kitchensink project that lets you run it out of a single file, if you're so inclined.
config = Configurator()
config.add_route('hello', '/hello/{name}')
config.add_view(hello_world, route_name='hello')
is really just boilerplate, which is better done as a decorator. Count how many times the word 'hello' appears in that snippet above. And this is just for a hello world program. Once you start on a real app, that's only going to multiply. from pyramid.view import view_config
from pyramid.response import Response
from paste.httpserver import serve
@view_config(route_name='hello')
def hello_world(request):
return Response('Hello %(person)s' % request.matchdict)
if __name__ == '__main__':
config = Configurator()
config.add_route('hello', '/hello/{person}')
config.scan()
serve(config.make_wsgi_app())
The config.scan() bit causes the @view_config decorators to be picked up. So we do have some decorators, although they don't populate an external registry (by design).The rationale for putting the route ordering in imperative code instead of using decorator declaration order is in the document I linked. I'm not particularly interested in crippling Pyramid for larger apps to race to the bottom of the LOC count. It's succinct enough and works for truly large apps too.
@view_config(route_name='hello', request_method='GET')
def get_hello(request):
return Response('a GET request for %s' % request.matchdict['name'])
@view_config(route_name='hello', request_method='POST')
def post_hello(request):
return Response('stored info')
config = Configurator()
config.add_route('hello', '/hello/{name}')
config.scan()
app = config.make_wsgi_app() @route('/hello/:name', method='GET')
def hello_get(name):
return 'Hello %s' % name
@route('/hello/:name', method='POST')
def hello_post(name):
return 'Hello %s' % name
Pyramid permits a larger variety of predicates (including custom ones), however: https://docs.pylonsproject.org/projects/pyramid/1.2/narr/vie...Is this for real? Do people find the difference between the style of these micro-frameworks substantial? Maybe I've been out of Python-land for too long, but 70% of these look almost identical (raising exceptions for redirects, a combination of lists and naming conventions or decorators for routes/methods, etc.) and the other 30% look awful.
Furthermore, when all of the frameworks are basically the same, isn't a much more important question what scenario they were designed for, or what extra features they have, or performance, or how big a community they have? (Even where the author seems to have reasonable criteria, like WSGI, he doesn't seem able to look up that web.py is WSGI-based.) And seriously, does anyone care about Python 3 and/or PyPy support in 2011?
Another way of putting this: do the criteria that the author lists match anyone's criteria who is currently writing Python web applications in the real world?
sudo pip install -u flask
cd /usr/local/lib/python2.6/dist-packages
find flask/ werkzeug/ jinja2/ -name '*.py' | xargs wc
...
34936 127298 1658380 total
Werkzeug alone has 18KLOC and does not ship with tests.With this little script (http://paste.pocoo.org/show/465885/) I get the following results:
Flask 1467 LOC
Jinja2 6560 LOC
Werkzeug 9923 LOC
Bottle 1910 LOC
(FWIW)Not all of the code that is in Jinja2 or Werkzeug is used by the average Flask application. Also Flask does a lot more than Bottle, even for the same things. The routing system behind Werkzeug itself already comes close to 1KLOC (and for good reasons). Which is why I think that any comparison between Bottle and Flask is pretty pointless, it's not really a fair fight for either.
For Flask it was never a goal to have less code than another framework, in fact, from our perspective that's quite a pointless goal.
It would be much more interesting for potential users if people started comparing lines of documentation(LOD) and showed the quotient lines of tests/lines of code.
With those criteria, I'm sort of switching between Flask and Tornado right now.
Speed is a major consideration with any python framework, too. You've got serious threading concerns. Even with Tornado, advertised as non-blocking, the default solution is nginx running against a whole bunch of tornado threads. ...
You can do that with Flask as well, in fact the documentation there is an entire document describing various approaches[1].
Blueprints are a "new" concept but the approach is basically the same, however they are able to interact with the application at a Flask-level, they can modify the application and share information like the configuration.
This is something Bottle doesn't support at a framework level, forcing you to abuse the functionality it provides from a semantical standpoint.
This concept is more difficult to understand but than again it is very trivial compared to other concepts any web developer should grasp.
You don't have to use them. Just do the Bottle way if you prefer.
Interesting if somewhat very biased.
Generally I would consider any framework which requires (almost) no setup requirements to be a microframework. This is opposed to frameworks which require a basic configuration, directory layout or certain files to be present.
However there are a lot of other people with other definitions regarding this, the distinction is not at all very clear for example there are people that consider being written in a single file to be a distinguishing feature of microframeworks.
Here is how we (Flask developers) define microframework: http://flask.pocoo.org/docs/foreword/#what-does-micro-mean
Obviously, I'm not serious here; but there's some truth in it. I.e. You'll see some companies ask for django or rails developers; not for flask python hacker right ;-)