You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Bottle is a fast, simple and lightweight WSGI_ micro web-framework for Python_. It is distributed as a single file module and has no dependencies other than the `Python Standard Library <http://docs.python.org/library/>`_.
32
+
Bottle is a fast, simple and lightweight WSGI_ micro web-framework for Python_. It is distributed as a single file module and has no dependencies other than the `Python Standard Library <https://docs.python.org/library/>`_.
33
33
34
34
* **Routing:** Requests to function-call mapping with support for clean and dynamic URLs.
35
-
* **Templates:** Fast `built-in template engine <http://bottlepy.org/docs/dev/tutorial.html#tutorial-templates>`_ and support for mako_, jinja2_ and cheetah_ templates.
35
+
* **Templates:** Fast `built-in template engine <https://bottlepy.org/docs/dev/tutorial.html#tutorial-templates>`_ and support for mako_, jinja2_ and cheetah_ templates.
36
36
* **Utilities:** Convenient access to form data, file uploads, cookies, headers and other HTTP features.
37
37
* **Server:** Built-in development server and ready-to-use adapters for a wide range of WSGI_ capable HTTP server (e.g. gunicorn_, paste_ or cheroot_).
Copy file name to clipboardExpand all lines: docs/async.rst
+6-6Lines changed: 6 additions & 6 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -1,12 +1,12 @@
1
1
Asynchronous Applications
2
2
=========================
3
3
4
-
Asynchronous design patterns don't mix well with the synchronous nature of `WSGI <http://www.python.org/dev/peps/pep-3333/>`_. This is why most asynchronous frameworks (tornado, twisted, ...) implement a specialized API to expose their asynchronous features. Bottle is a WSGI framework and shares the synchronous nature of WSGI, but thanks to the awesome `gevent project <http://www.gevent.org/>`_, it is still possible to write asynchronous applications with bottle. This article documents the usage of Bottle with Asynchronous WSGI.
4
+
Asynchronous design patterns don't mix well with the synchronous nature of `WSGI <https://www.python.org/dev/peps/pep-3333/>`_. This is why most asynchronous frameworks (tornado, twisted, ...) implement a specialized API to expose their asynchronous features. Bottle is a WSGI framework and shares the synchronous nature of WSGI, but thanks to the awesome `gevent project <https://www.gevent.org/>`_, it is still possible to write asynchronous applications with bottle. This article documents the usage of Bottle with Asynchronous WSGI.
5
5
6
6
The Limits of Synchronous WSGI
7
7
-------------------------------
8
8
9
-
Briefly worded, the `WSGI specification (pep 3333) <http://www.python.org/dev/peps/pep-3333/>`_ defines a request/response circle as follows: The application callable is invoked once for each request and must return a body iterator. The server then iterates over the body and writes each chunk to the socket. As soon as the body iterator is exhausted, the client connection is closed.
9
+
Briefly worded, the `WSGI specification (pep 3333) <https://www.python.org/dev/peps/pep-3333/>`_ defines a request/response circle as follows: The application callable is invoked once for each request and must return a body iterator. The server then iterates over the body and writes each chunk to the socket. As soon as the body iterator is exhausted, the client connection is closed.
10
10
11
11
Simple enough, but there is a snag: All this happens synchronously. If your application needs to wait for data (IO, sockets, databases, ...), it must either yield empty strings (busy wait) or block the current thread. Both solutions occupy the handling thread and prevent it from answering new requests. There is consequently only one ongoing request per thread.
12
12
@@ -17,7 +17,7 @@ Greenlets to the rescue
17
17
18
18
Most servers limit the size of their worker pools to a relatively low number of concurrent threads, due to the high overhead involved in switching between and creating new threads. While threads are cheap compared to processes (forks), they are still expensive to create for each new connection.
19
19
20
-
The `gevent <http://www.gevent.org/>`_ module adds *greenlets* to the mix. Greenlets behave similar to traditional threads, but are very cheap to create. A gevent-based server can spawn thousands of greenlets (one for each connection) with almost no overhead. Blocking individual greenlets has no impact on the servers ability to accept new requests. The number of concurrent connections is virtually unlimited.
20
+
The `gevent <https://www.gevent.org/>`_ module adds *greenlets* to the mix. Greenlets behave similar to traditional threads, but are very cheap to create. A gevent-based server can spawn thousands of greenlets (one for each connection) with almost no overhead. Blocking individual greenlets has no impact on the servers ability to accept new requests. The number of concurrent connections is virtually unlimited.
21
21
22
22
This makes creating asynchronous applications incredibly easy, because they look and feel like synchronous applications. A gevent-based server is actually not asynchronous, but massively multi-threaded. Here is an example::
23
23
@@ -51,7 +51,7 @@ If you run this script and point your browser to ``http://localhost:8080/stream`
51
51
Event Callbacks
52
52
---------------
53
53
54
-
A very common design pattern in asynchronous frameworks (including tornado, twisted, node.js and friends) is to use non-blocking APIs and bind callbacks to asynchronous events. The socket object is kept open until it is closed explicitly to allow callbacks to write to the socket at a later point. Here is an example based on the `tornado library <http://www.tornadoweb.org/documentation#non-blocking-asynchronous-requests>`_::
54
+
A very common design pattern in asynchronous frameworks (including tornado, twisted, node.js and friends) is to use non-blocking APIs and bind callbacks to asynchronous events. The socket object is kept open until it is closed explicitly to allow callbacks to write to the socket at a later point. Here is an example based on the `tornado library <https://www.tornadoweb.org/documentation#non-blocking-asynchronous-requests>`_::
55
55
56
56
class MainHandler(tornado.web.RequestHandler):
57
57
@tornado.web.asynchronous
@@ -64,7 +64,7 @@ The main benefit is that the request handler terminates early. The handling thre
64
64
65
65
With Gevent+WSGI, things are different: First, terminating early has no benefit because we have an unlimited pool of (pseudo)threads to accept new connections. Second, we cannot terminate early because that would close the socket (as required by WSGI). Third, we must return an iterable to conform to WSGI.
66
66
67
-
In order to conform to the WSGI standard, all we have to do is to return a body iterable that we can write to asynchronously. With the help of `gevent.queue <http://www.gevent.org/gevent.queue.html>`_, we can *simulate* a detached socket and rewrite the previous example as follows::
67
+
In order to conform to the WSGI standard, all we have to do is to return a body iterable that we can write to asynchronously. With the help of `gevent.queue <https://www.gevent.org/gevent.queue.html>`_, we can *simulate* a detached socket and rewrite the previous example as follows::
68
68
69
69
@route('/fetch')
70
70
def fetch():
@@ -83,7 +83,7 @@ Finally: WebSockets
83
83
84
84
Lets forget about the low-level details for a while and speak about WebSockets. Since you are reading this article, you probably know what WebSockets are: A bidirectional communication channel between a browser (client) and a web application (server).
85
85
86
-
Thankfully the `gevent-websocket <http://pypi.python.org/pypi/gevent-websocket/>`_ package does all the hard work for us. Here is a simple WebSocket endpoint that receives messages and just sends them back to the client::
86
+
Thankfully the `gevent-websocket <https://pypi.python.org/pypi/gevent-websocket/>`_ package does all the hard work for us. Here is a simple WebSocket endpoint that receives messages and just sends them back to the client::
Copy file name to clipboardExpand all lines: docs/changelog.rst
+4-4Lines changed: 4 additions & 4 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -123,7 +123,7 @@ These changes might require special care when updating.
123
123
124
124
* :class:`Bottle` instances are now context managers. If used in a with-statement, the default application changes to the specific instance and the shortcuts for many instance methods can be used.
125
125
* Added support for ``PATCH`` requests and the :meth:`Bottle.patch` decorator.
126
-
* Added `aiohttp <http://aiohttp.readthedocs.io/en/stable/>`_ and `uvloop <https://github.com/MagicStack/uvloop>`_ server adapters.
126
+
* Added `aiohttp <https://aiohttp.readthedocs.io/en/stable/>`_ and `uvloop <https://github.com/MagicStack/uvloop>`_ server adapters.
127
127
* Added command-line arguments for config from json or ini files.
128
128
* :meth:`Bottle.mount` now recognizes instances of :class:`Bottle` and mounts them with significantly less overhead than other WSGI applications.
129
129
* The :attr:`Request.json <BaseRequest.json>` property now accepts ``application/json-rpc`` requests.
@@ -145,7 +145,7 @@ Release 0.12
145
145
* Removed the ``Request.MAX_PARAMS`` limit. The hash collision bug in CPythons dict() implementation was fixed over a year ago. If you are still using Python 2.5 in production, consider upgrading or at least make sure that you get security fixed from your distributor.
146
146
* New :class:`ConfigDict` API (see :doc:`configuration`)
147
147
148
-
More information can be found in this `development blog post <http://blog.bottlepy.org/2013/07/19/preview-bottle-012.html>`_.
148
+
More information can be found in this `development blog post <https://blog.bottlepy.org/2013/07/19/preview-bottle-012.html>`_.
149
149
150
150
151
151
Release 0.11
@@ -154,7 +154,7 @@ Release 0.11
154
154
* Native support for Python 2.x and 3.x syntax. No need to run 2to3 anymore.
155
155
* Support for partial downloads (``Range`` header) in :func:`static_file`.
156
156
* The new :class:`ResourceManager` interface helps locating files bundled with an application.
157
-
* Added a server adapter for `waitress <http://docs.pylonsproject.org/projects/waitress/en/latest/>`_.
157
+
* Added a server adapter for `waitress <https://docs.pylonsproject.org/projects/waitress/en/latest/>`_.
158
158
* New :meth:`Bottle.merge` method to install all routes from one application into another.
159
159
* New :attr:`Request.app <BaseRequest.app>` property to get the application object that handles a request.
160
160
* Added :meth:`FormsDict.decode()` to get an all-unicode version (needed by WTForms).
@@ -212,7 +212,7 @@ Release 0.9
212
212
213
213
* A brand new plugin-API. See :doc:`plugins/index` and :doc:`plugins/dev` for details.
214
214
* The :func:`route` decorator got a lot of new features. See :meth:`Bottle.route` for details.
215
-
* New server adapters for `gevent <http://www.gevent.org/>`_, `meinheld <http://meinheld.org/>`_ and `bjoern <https://github.com/jonashaag/bjoern>`_.
215
+
* New server adapters for `gevent <https://www.gevent.org/>`_, `meinheld <https://meinheld.org/>`_ and `bjoern <https://github.com/jonashaag/bjoern>`_.
216
216
* Support for SimpleTAL templates.
217
217
* Better runtime exception handling for mako templates in debug mode.
218
218
* Lots of documentation, fixes and small improvements.
The built-in development server is base on `wsgiref WSGIServer <http://docs.python.org/library/wsgiref.html#module-wsgiref.simple_server>`_, which is a very simple non-threading HTTP server implementation. This is perfectly fine for development, but may become a performance bottleneck when server load increases.
44
+
The built-in development server is base on `wsgiref WSGIServer <https://docs.python.org/library/wsgiref.html#module-wsgiref.simple_server>`_, which is a very simple non-threading HTTP server implementation. This is perfectly fine for development, but may become a performance bottleneck when server load increases.
45
45
46
46
The easiest way to increase performance is to install a multi-threaded server library like cheroot_ or gunicorn_ and tell Bottle to use that instead of the single-threaded wsgiref server::
* **Download:** Development branch as `tar archive <http://github.com/bottlepy/bottle/tarball/master>`_ or `zip file <http://github.com/bottlepy/bottle/zipball/master>`_.
23
+
* **Download:** Development branch as `tar archive <https://github.com/bottlepy/bottle/tarball/master>`_ or `zip file <https://github.com/bottlepy/bottle/zipball/master>`_.
24
24
25
25
26
26
Releases and Updates
27
27
--------------------
28
28
29
-
Bottle is released at irregular intervals and distributed through `PyPI <http://pypi.python.org/pypi/bottle>`_. Release candidates are only available from the git repository mentioned above. Debian and many other Linux distributions offer packages.
29
+
Bottle is released at irregular intervals and distributed through `PyPI <https://pypi.python.org/pypi/bottle>`_. Release candidates are only available from the git repository mentioned above. Debian and many other Linux distributions offer packages.
30
30
31
31
The Bottle version number splits into three parts (**major.minor.patch**) but does not follow the rules of `SemVer <https://semver.org/>`_. Instead, you can usually rely on the following rules:
0 commit comments