Hacker News new | past | comments | ask | show | jobs | submit login
Bottle: Single-File Python Web Framework (bottlepy.org)
213 points by dpatru on July 17, 2011 | hide | past | web | favorite | 52 comments

It looks exactly like Itty (since 2009, updated as recently as 2011): https://github.com/toastdriven/itty

The only differences I see are minor name changes. I'll have to compare the source code.

EDIT: It appears to be an unrelated codebase with a lot of improvements (for example, proper cookie support). Looks like I'll need to be updating my projects.

The disqus comments on the page are entirely correct: it should come standard with python (or something like it). I've used it a few times and it's just elegant and would match "batteries included" perfectly.

A full web framework is not something you want to come standard with Python. Putting Bottle, Flask, Django, {your_favorite} inside the standard library would pretty much kill it. Development would screech almost to a halt since Python generally releases less often than any of these frameworks.

For example, we released 3.2 in Spring '11. There will be no new features released until 3.3, which is slated to come out in Fall '12 - about 1.5 years. In comparison, the popular Flask framework is about 1.5 years old and has had ~8 point releases, and it can add features whenever it wants at whatever rate it wants. If Armin wants to make a new feature today, he can do that and release it today if he wants.

On top of that, web frameworks are like a religion that we would have to choose. There's currently a separation of church and state that has worked well in the community and allowed different frameworks to do different things at different paces. I think we should keep that.

I agree on you regarding a full stack web framework with it's own community such as Django but a lightweight, minimal web framework would be a useful addition to the standard library, surely?

Putting something in standard lib effectively kills it. It doesn't mature, it turns into an adult child actor. Forever 'young'

I don't think their really should be a standard library for Python. There should be a base, and a much more proactively revved base library, but not a standard library. Part of installing python would be installing the base.

I think the standard library is great. It's good to know that there is a "batteries complete" library that you can really on, that won't change its API for years. Being standard, it's well documented, well vetted, and lots of people know it.

There needs to be a wider repo, but pip / easy_install does that OK.

What does need to change - there needs to be more "library2" modules. urllib wasn't good enough, so they made "urllib2". Likewise, there's lots of old, outdated modules that could be supplanted.

Brian, you are completely wrong. The x2 modules need to go away. They are confusing, the "standard lib" is mostly shit. And it is fixed in time. If it were writing I would describe it as a, "hack, rambling, incoherent, amateur" piece of work.

The usability of pip is abysmal. You don't even get usage by just typing "pip" with no arguments. Look at brew for direction.

Python makes me sad.

Sure, it would be great, but whatever we consider would have to be very complete and very mature. There's not much room for evolution in standard library APIs, and with lightweight frameworks being relatively new to the scene, the framework developers themselves probably do not want to give up their current freedom to grow in whatever direction they please.

If we look back at this in a few years, maybe it's worth considering as usage grows, APIs are more locked down, and a clear winner shines through. Right now, any inclusion would be months of bike shedding, assuming any of these framework developers are willing to give up external maintenance of their products and go 100% into the standard library.

wsgiref is already in the standard library and is as about as minimal as you can get. Why add more?

Better to have pip included as standard and make the framework of your choice a one-line install.

And end up with something like Perl's CGI? Request/Response favorite flavors seems to change every 2-3 years. I wouldn't want Python to suffer from that bloat.

It seems like being single-file is mostly gimmick. What are the drawbacks to creating a folder with an __init__.py and a handful of readably-long files?

Agreed. The project is ~2700 lines of code all jammed into a single file. Each component is pretty clearly separated from the others with big comment headers, but I don't understand what advantage this has over separate files other than the ability to advertise that it is a single file library.

Perhaps they're not trying to advertise to the Python crowd but to the PHP and JavaScript crowd who might be suckered in by the "Ooh, I only have to include one file?" line.

JQuery is single file too and that's a big part of it's attraction. Simplicity is a huge plus, not only for users, but also for the developer who is forced to be disciplined.

I haven't used bottle yet (just starting), but I'm very impressed with the templating code which seems very powerful and simple. Including the templating system along with the rest of the framework in a single file, forced the developer to think about it more.

But part of the advantage with jQuery being single-file there is ease of deployment. Python isn't quite as handicapped in this areas as Javascript is. A single line in requirements.txt can add something as complex a complex library to your project without a second thought.

And you'll end up with the complexity of dependencies with mismatched and/or incompatible versions. Adding a dependency explicitly to the source code is the ultimate, albeit somewhat inefficient, solution which is often useful. In Python, for example, BeautifulSoup has long recommended this practice.

See also the SQLite amalgamation for another example of a single-file deployment: http://www.sqlite.org/amalgamation.html

(Client-side) JavaScript doesn't have a simple, builtin pattern for module dependency the way Python does, though.

I imagine it's about being able to include the whole framework inside your project, without inflating it with a number of files or even having to create a new folder.

If you are using pip and virtualenv (which are currently understood as "best practice" in the Python world), it's as simple as running "pip install PACKAGE==VERSION" (or, better, adding "PACKAGE==VERSION" to your requirements.txt file). Even if it was expected that people would frequently fork their own version and drop it in their application, a package is still just be a directory with a few .py files. Hardly an issue for version control systems or even setuptools, and it has the advantage that your application code is separated from the forked framework code.

Looking at the source is just one search away, instead of having to navigate many files or build a tag file or whatever. Also provides an incentive to keep shit tidy.

"Also provides an incentive to keep shit tidy." This :)

I've used this quite a bit and love it. My favorite part is that there are no dependencies (that aren't in the standard library).

This is exactly what I was looking for. Got up this morning and it was #1 on HN. This is why I <3 HN. Thanks for solving my problems again :-)

Bottle has been around for a while and is great. But is there something new or about to reach proverbial "1.0" status?

For those interested in single-file frameworks, there is also Mojolicious in Perl and Fat-Free in PHP.

How does it compare with flask?

I used bottle for one project, but switched to Flask for everything once it was released. In my opinion the future is very bright for Flask (extensions, blueprints, community). The code and libraries it is built on top of are all extremely high quality.

Basically, bottle was here and things were good, and then Armin decided to announce Flask as an April Fools joke and ate poor bottle's lunch.

Bottle and Flask are similar enough, but I think Flask has more momentum and support.

Armin sums up the differences pretty well in a comment on StackOverflow[1]:

"The big difference is that Flask is based on other technologies such as Werkzeug and Jinja2 that exist for a longer time and it does not try to reinvent things. Bottle on the other hand tries to stick to the one-file approach. [...]"

[1] http://stackoverflow.com/questions/4941145/python-flask-vs-b...

Lots of similarities, one of the bigger differences is that Flask is standing on the shoulders of giants whereas Bottle is turtles all the way down. If a lack of dependencies is a big deal to you, then Bottle wins, but given Python's packaging system, I don't see situations where that would matter a lot.

Armin wrote a post back in January regarding mergers in the Python world of frameworks.


I'm not Armin, but I've used both extensively, and the main thing I can feel is that Bottle lacks the elegant power of Flask's underlying libraries. Django suffers from this, too, but in Bottle it's even more obvious: Werkzeug and Jinja2 are deliriously powerful libraries! I remember Armin once talking about how instructional and useful it could be to derive a custom Flask from Werkzeug, and watching his methodology, it became quite apparent that Werkzeug's the best way to do WSGI at the low level. Jinja2's in a similar position; if you've ever read through Django's templating library, you'd agree.

Extremely well built and easy to use from a UX (DX? Developer Experience?) perspective. I have recently been using Sinatra and am loving these extremely minimal frameworks. We just need something like Heroku for Python. Gondor maybe?

Well, in fairness, Heroku is now the Heroku for Python. The new Cedar stack (unofficially) supports Python, and some of the frameworks are already being tested on it (http://docs.pylonsproject.org/projects/pyramid_cookbook/dev/...)

I managed to get into the betas for both ep.io and gondor, but neither has anything near the polish that the Heroku guys have had years to work on.

Is it just me or is the first example on their front page a great example of XSS? Unless their standard string formatting routines are performing escaping, this is pretty awful.

Seems to me to be another micro web framework influenced heavily by Sinatra.

Do you know enough about the Python ecosystem to make that assessment? Aaron Swartz's web.py was around as a single-file web micro-framework years before Sinatra even existed. An early version of reddit, after they switched from Common Lisp to Python, was built starting with web.py.

I know that web.py was around years before Sinatra. But URL routing in Bottle is more similar to Sinatra than it is to the URL dispatching via a tuple at the top of a file. Even so, perhaps Bottle is influenced more by web.py. That doesn't mean there aren't a ton of ports of Sinatra (like Express for node.js, Scalatra) or those influence by Sinatra like itty (http://toastdriven.com/blog/2009/mar/07/itty-sinatra-inspire...) or even perhaps Flask.

I even noticed a comment above that said Bottle looks just like Itty. Yet because I brought up the Ruby framework that Itty is essentially a port of, I'm getting down-voted like crazy. I will never understand why Python people dislike Ruby so much, and vice versa.

> But URL routing in Bottle is more similar to Sinatra than it is to the URL dispatching via a tuple at the top of a file.

Decorators, a Python 2.5 feature, weren't around when web.py was first released, so they couldn't have been used initially. Even after Python 2.5 came out, it took some time for decorators to be widely embraced. But routing and other kinds of dispatching (e.g. adapters and multimethods) are an obvious and indeed commonplace use of them.

I didn't down-vote you. I did get ever so slightly annoyed with your implication that Sinatra was the first to do this kind of thing and therefore necessarily a source of influence. Neither half of this claim is correct. Sinatra wasn't the first. Even if it were, it need not have been an influence; I wouldn't claim that web.py had to have influenced Sinatra just because it preceded it.

Werkzeug, the library which provides the routes, predates Sinatra by at least a year (2007 compared to 2008 for Sinatra) and might be even older; it predates the SVN->git switch for Pocoo.

Python people don't dislike Ruby, they dislike the Ruby community's habit of assuming that Ruby somehow did it first and did it better. :3

I ♥ Bottle!

Anyone who've used web.py and Bottle (for a real project) and care to comment on the pros/cons of both? I'm quite familiar with web.py but not so much with Bottle.

Used it early and extensively for a pretty good sized project. In my experience what really happens on a long-lived project is that you end up writing and assembling your own framework on top of the basics that are provided. Not a bad thing if you think you're gonna end up growing a lot of your own infra anyways..

I think mostly I'd use microframeworks like this in the future to do small projects and early prototyping.. or if I thought the project had special needs that was going to make using something like Django a particularly challenging match.

It's an interesting dynamic. I'm going through a similar thought process except one level of abstraction higher (at the pseudo-CMS level on top of Django). I'm sure similar debates happen at lower levels of abstraction too.

You've got to decide for yourself where your 'reinventing the wheel' cutoff point is. For some people it's flipping binary bits, for others, anything lower level than configuring Drupal modules is just a waste of time.

I used this thing in a desktop app that consumed a RESTful API service and received notifications (HTTP POSTs) from the API service.

At a high rate, bottle just dies. So if you have a situation where you are making many requests to it, be careful; your mileage may vary.

What WSGI server were you deploying on? I'm thinking of using Bottle for some providing some REST services, so any details you can provide would be helpful.

I can't speak for the parent poster, but I deployed bottle with the grandparent poster without any significant performance issues*. This was first under mod_wsgi, then paste.deploy once mod_wsgi got to be a headache, and now I'm looking at gunicorn as a simpler alternative to paste.deploy.

So, why the asterisk next to "no issues"? I was able to wedge our app once by doing frequent, unbuffered, blocking socket.reads for one byte at a time in our RPC library... the GIL is a fearsome thing and it didn't play well with this strategy under highly concurrent request loads. I don't see that as a bottle problem, though.

If you're anticipating high loads, though, I wholly recommend looking at Brubeck (http://brubeck.io/) or Tornado (http://www.tornadoweb.org/)

I'd be curious for the details other asked for (define high rate, and how did you serve bottle)... Bottle services requests admirably. Not much there other than regexing your path and calling your function. If you had scalability issues I'd be tempted to believe it wasn't bottle code that was causing your problem (assuming you were using a real webserver to serve bottle workers).

I was considering using it for an internal webpage in my company. In my particular use case, I would have needed a separate backend thread that watches some files and gives some data to the server thread(s) with proper synchronization. However, because of the GIL, I decided that using threads like this only adds complexity to my code without improving performance. In the end, I chose Twisted, which supports async. Using Twisted also allows me to use hanging GETs without worrying about needing too many server threads.

I would have been happy to use Bottle if i) it had a feature that lets me specify FDs to watch and associated callbacks, like what I could do if I directly controlled the server select loop and ii) Python had built-in support for reader-writer locks.

Twisted had async support but it's documentation could be more comprehensive. I understood the programming model, classes and methods well enough to use it for my project only after tinkering with code, not from just reading documentation or looking at examples.

http://bottlepy.org/docs/dev/async.html might be interesting for you.

I use bottle on top of gevent for two RESTful services, one of which sees peak 100's of requests per second. Bottle is perfect for my use case: basic routing, and a simple management / monitoring UI. I'm quite satisfied.

what this framework is missing compared to Django

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