Home | People | Web Frameworks | Emulation |
---|---|---|---|
Python |
This document provides an analysis of Python Web modules and frameworks, along with a comparison of these frameworks to Java 2 Enterprise Edition standard technologies. Whilst many different Python Web modules and frameworks exist (see the "Web Frameworks Overview" for details), this document only attempts to review those frameworks which provide environments comparable to the more complete J2EE implementations.
Author: Paul Boddie (paul@boddie.org.uk)
This document does not attempt to address issues such as transaction or messaging support in either Java-oriented or Python-oriented technologies. Currently, the document focuses on technologies which are convenient to package into a product, along with the products available to Python developers.
This document is deliberately incomplete - it will be improved and completed over time, especially with comments from the Python Web development community.
The Java 2 Enterprise Edition technologies attempt to address the most common needs of enterprise application developers. It is therefore interesting to see which alternatives exist within Python-oriented frameworks.
Servlets are components which receive Web requests, typically over HTTP, and which respond to such requests by providing output suitable for display by a Web browser. Originally, servlets were the Java equivalent of CGI programs or scripts.
The implementation of a basic servlet typically includes a number of methods which respond to the different kinds of requests possible in the protocol used to access the application concerned. Since HTTP-related protocols are the most common for Web applications, implementations of methods handling the "GET" and "POST" request types are typically provided, and each of these methods will access a response object provided by the Web server (or "servlet container") in order to produce the application's output for the resource represented by the servlet.
Python has long been an obvious choice for "dynamic", server-side Web applications, from simple CGI scripts to more complicated applications. Whilst most frameworks provide something equivalent to servlets, some frameworks provide mechanisms which are closer to the servlet concept than others.
The foundations of servlet support in Webware are found in the WebKit package, where the classes appear to resemble Java servlets reasonably closely.
JavaServer Pages (JSP) is a program-code-inside-HTML template technology, similar to Active Server Pages and other *SP technologies, but with Java as the programming language of choice.
A JSP resource is composed principally of textual mark-up, usually HTML, which provides a representation of a page to be displayed to users of an application. Mixed in with the HTML are special JSP elements which provide dynamic aspects of the final page, such as substitution of text, inclusion of page components, and repetition of page components. The inputs to the JSP resource which determine the behaviour of such dynamic aspects are typically the properties of an incoming request from the user, combined with additional attributes of the request which are set by the application.
Java Beans are effectively objects with standardised method names which make it easier to refer to "properties" of an object. JSP resources can declare their usage of beans and pass information into beans for processing, and then extract information from beans for presentation.
Scriptlets are program fragments which perform more complicated presentation-oriented logic than that permitted through the interaction with beans. With scriptlets, it is possible to construct a loop which wraps up a fragment of HTML; this fragment could then be repeated according to the amount or nature of the data available. Scriptlets appear inside special comment-like tags.
Tag libraries provide a means of extending the "vocabulary" available in the form of special JSP tags. Each such tag can be defined to perform application-level work and to produce output which is then incorporated into the final page. Use of tag libraries should reduce the amount of presentation-oriented logic within JSP resources in the form of scriptlets, whilst concentrating such logic in one place - the tag library's implementation for a given tag.
Many *SP systems have been invented for Python. Indeed, there can be a certain amount of confusion about the number of distinct frameworks available and their relation to each other. For a comparable technology, however, one would look for support for clean interaction with application components (beans), support for the extension of the "vocabulary" provided through tag libraries, and the ability to embed presentation-oriented logic within resources in a similar fashion to that provided by scriptlets.
Interestingly, Webware's PSP technology does not support the equivalent of the "jsp:useBean" series of tags and associated functionality, although the Cans proposal suggests the possibility of such functionality in the future. It is arguably the case that developers are often more comfortable with the scriptlet paradigm and that bean manipulation through tags is often ignored.
SkunkWeb's STML appears to support something like the "jsp:useBean" functionality through its own ":component:" tag.
NOTE: Mention other template technologies, such as DTML, ZPT, etc.
The J2EE framework attempts to provide more than just an HTML template system. Session beans are application-level objects through which interactions between the application and its users take place, and the state of those interactions is held in instances of session beans.
Two kinds of session beans are mentioned in the J2EE framework: stateless and stateful session beans. The difference between the two kinds is that stateless beans remember nothing about previous activities from one invocation to the next, whereas stateful beans do remember things and can be used to hold details of a particular user's activities, for example.
In short, stateless beans are effectively "passive" interfaces to application functionality, whereas stateful beans are likely to provide many instances of the same interface, each potentially specialised for different users. For Web applications, it is arguably more likely that stateless beans will be in widespread use, although stateful beans could be used in conjunction with sessions provided by the servlet container.
Session beans are created using a "factory"-style mechanism known as a "home", with different "home" instances identified through a reference defined in the application and fetched using the Java Naming and Directory Interface (JNDI) API.
Most Python Web frameworks can trivially support access to application components through the use of "import" statements either in servlet or scriptlet code (or both). The provision of an abstract interface for acquiring objects by application-specific identifier is apparently not so widespread. Moreover, the interface to application-level components is not likely to be as tightly legislated as is found in the J2EE framework, although one might argue that the benefits of strict method naming stop short of being able to automatically share components between different applications.
Whereas session beans provide a means of supporting interactions between an application and its users, entity beans attempt to support interactions between application components and the data available to the application. Each entity bean represents a bundle of data in the form of an object (or bean instance).
Like session beans, entity beans are obtained through an abstract interface providing "home" objects, which in turn provide entity beans upon request. Using a particular "find" method, one or several object references can be obtained, each representing data to be accessed in the application.
A container is an abstraction over a particular storage system, and container managed persistence is the mechanism by which data is retrieved from such a storage system, encapsulated by different kinds of objects and, if appropriate, converted back from such objects into representations used by the storage system concerned, all without the objects involved being aware of how the mechanism is implemented. What makes container managed persistence special is that it typically attempts to provide a generic object-oriented abstraction over the retrieval and storage of data.
Where persistence is managed by the beans themselves, such beans must be aware of how they are represented in a storage system. However, there are certain situations where this is necessary:
Access to databases is frequently the next step for Web application developers after creating simple dynamic sites. Moreover, it is an attractive notion that data stored in database systems should be accessible using object-like abstractions, as opposed to issuing SQL queries and retrieving result sets. As a result, a number of Python frameworks attempt to support object-relational or object-oriented data stores.
A pervasive concept in Enterprise JavaBeans is that of a transaction, and there are several ways that transactions can be created and used within an appropriate "container". In a fashion similar to that of many relational database management systems, EJB transactions provide the possibility for developers to support changes to data within an isolated context, where such changes can subsequently be "undone" if they prove to be inappropriate.
The EJB specification mandates two different kinds of transaction management. One is "bean managed transaction management" where the beans (the business objects which access and manipulate data) control the creation and completion or destruction of transactions; in this style of management, code appears in the bean objects to create transactions and to "commit" or "rollback" such changes explicitly. The other kind of transaction management is "container managed transaction management" where the container (in practice, the application server) controls the transactions according to guidelines provided by the developer; in this style of management, the transaction handling is mostly omitted from the code, although in practice, the developer still needs to indicate conditions where transactions would be rolled back (in other words, abandoned, with the changes made being discarded).
The EJB transaction support is ambitious in its scope, but potentially provides support for activities which would otherwise need to be written over and over again by the developer for each application. Relatively few frameworks for Python seem to support anything other than access to databases in a transactional fashion, but one might question the need to provide support for transactional data manipulation "above" the database, especially if database access is tuned and performs well.
ZODB does seem to support transactions in that data residing in the object database can be changed and left uncommitted without overwriting the data which was there before. However, one might argue that as a database, ZODB does not really provide a container but a full database, albeit a lightweight and non-relational one.
One advantage that ZODB has over, for example, container managed transaction management with EJB session beans is that the rolling back of changes to data, like in any transactional database, should happen without the developer needing to have written code to make the beans react and restore their old data.
Here is a brief comparison of the major Python Web application frameworks and their support for J2EE-like features:
Features | Frameworks | |||||
---|---|---|---|---|---|---|
Webware | SkunkWeb | Zope | ||||
Servlets | WebKit provides classes which can support "bare" servlets | Does not appear to promote the servlet model, preferring to promote "hooks" from STML | Products and PythonMethods | |||
Presentation | JSP | Cheetah | PSP | STML | DTML | ZPT |
"jsp:useBean" | Cans are not accessible in PSP in a similar fashion and are not widely supported in Webware | ":component:" tag | DTML methods? | Uses a DOM-based model to access data, rather than a simple object-oriented approach | ||
Tag Libraries | Tags implemented as Products | Not entirely compatible with the notion of tag libraries | ||||
Scriptlets | Elementary control-flow concepts are supported | Supported | Tags support control-flow concepts | Iteration is supported using DTML tags, and arbitrary presentation can be coded in the tag classes | Like DTML iteration and other elementary control-flow concepts are supported | |
Session Beans | ZODB/ZEO | |||||
Entity Beans | Container Managed Persistence | MiddleKit | PyDO | ZODB/ZEO (albeit with a non-relational store) | ||
Transactions | Containers | ZODB/ZEO | ||||
Services (JTA/JTS) |
NOTE: To be written at some point in the future. This is really dependent on how deep the "Python Web Frameworks" document becomes in its analysis of the frameworks themselves.