Getting Started with Spring Python

Exclusive offer: get 50% off this eBook here
Spring Python 1.1

Spring Python 1.1 — Save 50%

Create powerful and versatile Spring Python applications using pragmatic libraries and useful abstractions

$26.99    $13.50
by Greg L. Turnquist | December 2010 | Open Source

Spring Python takes the concepts of the Spring Framework and Spring Security, and brings them to the world of Python. It isn't a simple line-by-line port of the code. Instead, it takes some powerful ideas that were discovered in the realm of Java, and pragmatically applies them in the world of Python.

Spring (Java) provides many simple, easy-to-use functional parts to assemble applications instead of a monolithic framework to extend. Spring Python uses this same approach. This means we can use as little or as much Spring Python as we need to get the job done for each Python application.

In this article, by Greg Lee Turnquist, author of Spring Python 1.1, we will learn:

  • About Spring Python's a non-invasive API which makes it easy to use other libraries without having to make major changes to your own code base
  • How Spring Python uses inversion of control to decouple object creation from object usage to empower the developer
  • How Spring Python provides the means to help professional Python developers by offering a non-invasive API to easily access advanced services
  • The ways in which Spring Python offers professional Java developers an easy way to mix Python and Java together through the combination of Python/Jython/Java
  • How to install the library from both binary and source code
  • How extensible Spring Python is, and also some links to the Spring Python community

 

Spring Python 1.1

Spring Python 1.1

Create powerful and versatile Spring Python applications using pragmatic libraries and useful abstractions

 

  • Maximize the use of Spring features in Python and develop impressive Spring Python applications
  • Explore the versatility of Spring Python by integrating it with frameworks, libraries, and tools
  • Discover the non-intrusive Spring way of wiring together Python components
  • Packed with hands-on-examples, case studies, and clear explanations for better understanding 
        Read more about this book      

(For more resources on this subject, see here.)

Spring Python for Python developers

You have already picked one of the most popular and technically powerful dynamic languages to develop software, Python. Spring Python makes it even easier to solve common problems encountered by Python developers every day.

Exploring Spring Python's non-invasive nature

Spring Python has a non-invasive nature, which means it is easy to adopt the parts that meet your needs, without rewriting huge blocks of code. For example, Pyro (http://pyro.sourceforge.net) is a 3rd party library that provides an easy way to make remote procedure calls.

In order to demonstrate the Spring way of non-invasiveness, let's code a simple service, publish it as a web service using Pyro's API, and then publish it using Spring Python's wrapper around Pyro. This will show the difference in how Spring Python simplifies API access for us, and how it makes the 3rd party library easier to use without as much rework to our own code.

  1. First, let's write a simple service that parses out the parameters from a web request string:

    class ParamParser(object): def parse_web_parms(self, parm): return [tuple(p.split("=")) for p in parm.split("&")]

  2. Now we can write a simple, functional piece of code that uses our service in order to have a working version.

    parser = ParamParser() parser.parse_web_parms("pages=5&article=Spring_Python")


    This is just instantiating the ParamParser and accessing the function. To make this a useful internet service, it needs to be instantiated on a central server and should be configured to listen for calls from clients.

  3. The next step is to advertise it as a web service using the API of Pyro. This will make it reachable by multiple Pyro clients. To do this, we define a daemon which will host our service on port 9000 and initialize it.

    daemon = Pyro.core.Daemon(host="localhost", port="9000") Pyro.core.initServer()

  4. Next, we create a Pyro object instance to act as proxy to our service as well as an instance of our ParamParser. We configure the proxy to delegate all method calls to our service.

    pyro_proxy = Pyro.core.ObjBase() parser = ParamParser() pyro_proxy.delegateTo(parser)

  5. Finally, we register the pyro_proxy object with the daemon, and startup a listen-dispatch loop so that it's ready to handle requests:

    daemon.connect(pyro_proxy, "mywebservice") daemon.requestLoop(True)

When we run this server code, an instance of our ParamParser will be created and advertised at PYROLOC://localhost:9000/mywebservice.

To make this service complete, we need to create a Pyro client that will call into our service. The proxy seamlessly transfers Python objects over the wire using the Pyro library, in this case the tuple of request parameters.

url_base = "PYROLOC://localhost:9000" client_proxy = Pyro.core.getProxyForURI( \ url_base + "/mywebservice") print client_proxy.parse_web_parms( \ "pages=5&article=Spring_Python")

The Pyro library is easy to use. One key factor is how our ParamParser never gets tightly coupled to the Pyro machinery used to serve it to remote clients. However, it's very invasive.

What if we had already developed a simple application on a single machine with lots of methods making use of our utility? In order to convert our application into a client-server application, we would have to rewrite it to use the Pyro client proxy pattern everywhere that it was called. If we miss any instances, we will have bugs that need to be cleaned up. If we had written automated tests, they would also have to be rewritten as well. Converting a simple, one-machine application into a multi-node application can quickly generate a lot of work.

That is where Spring Python comes in. It provides a different way of creating objects which makes it easy for us to replace a local object with a remoting mechanism such as Pyro.

Let's utilize Spring Python's container to create our parser and also to serve it up with Pyro.

from springpython.config import PythonConfig from springpython.config import Object from springpython.remoting.pyro import PyroServiceExporter from springpython.remoting.pyro import PyroProxyFactory class WebServiceContainer(PythonConfig): def __init__(self): super(WebServiceContainer, self).__init__() @Object(lazy_init=True) def my_web_server(self): return PyroServiceExporter(service=ParamParser(), service_name="mywebservice", service_port=9000) @Object(lazy_init=True) def my_web_client(self): myService = PyroProxyFactory() myService.service_url="PYROLOC://localhost:9000/mywebservice" return myService

With this container definition, it is easy to write both a server application as well as a client application. To spin up one instance of our Pyro server, we use the following code:

from springpython.context import ApplicationContext container = ApplicationContext(WebServiceContainer()) container.get_object("my_web_server")

The client application looks very similar.

from springpython.context import ApplicationContext container = ApplicationContext(WebServiceContainer()) myService = container.get_object("my_web_client") myService.parse_web_parms("pages=5&article=Spring_Python")

The Spring Python container works by containing all the definitions for creating key objects. We create an instance of the container, ask it for a specific object, and then use it.

This easily looks like just as much (if not more) code than using the Pyro API directly. So why is it considered less invasive?

Looking at the last block of code, we can see that we are no longer creating the parser or the Pyro proxy. Instead, we are relying on the container to create it for us. The Spring Python container decouples the creation of our parser, whether its for a local application, or if it uses Pyro to join them remotely. The server application doesn't know that it is being exported as a Pyro service, because all that information is stored in the WebServiceContainer. Any changes made to the container definition aren't seen by the server application code.

The same can be said for the client. By putting creation of the client inside the container, we don't have to know whether we are getting an instance of our service or a proxy. This means that additional changes can be made inside the definition of the container of Spring Python, without impacting our client and server apps. This makes it easy to split the server and client calls into separate scripts to be run in separate instances of Python or on separate nodes in our enterprise.

This demonstrates how it is possible to mix in remoting to our existing application. By using this pattern of delegating creation of key objects to the container, it is easy to start with simple object creation, and then layer on useful services such as remoting. Later in this book, we will also see how this makes it easy to add other services like transactions and security. Due to Spring Python's open ended design, we can easily create new services and add them on without having to alter the original framework.

Adding in some useful templates

In addition to the non-invasive ability to mix in services, Spring Python has several utilities that ease the usage of low level APIs through a template pattern. The template pattern involves capturing a logical flow of steps. What occurs at each step is customizable by the developer, while still maintaining the same overall sequence.

One example where a template would be useful is for writing a SQL query. Coding SQL queries by hand using Python's database API (http://www.python.org/dev/peps/pep-0249) is very tedious. We must properly handle errors and harvest the results. The extra code involved with connecting things together and handling issues is commonly referred to as plumbing code. Let's look at the following code to see how Python's database API functions.

The more plumbing code we have to maintain, the higher the cost. Having an application with dozens or hundreds of queries can become unwieldy, even cost prohibitive to maintain.

  1. Using Python's database API, we only have to write the following code once for setup.

    ### One time setup import MySQLdb conn = MySQLdb.connection(username="me", password"secret", hostname="localhost", db="springpython")

  2. Now let's use Python's database API to perform a single query.

    ### Repeated for every query cursor = conn.cursor() results = [] try: cursor.execute("""select title, air_date, episode_number, writer from tv_shows where name = %s""", ("Monty Python",)) for row in cursor.fetchall(): tvShow = TvShow(title=row[0], airDate=row[1], episodeNumber=row[2], writer=row[3]) results.append(tvShow) finally: try: cursor.close() except Exception: pass conn.close() return results


    The specialized code we wrote to look up TV shows is contained in the execute statement and also the part that creates an instance of TvShow. The rest is just plumbing code needed to handle errors, manage the database cursor, and iterate over the results.


    This may not look like much, but have you ever developed an application with just one SQL query? We could have dozens or even hundreds of queries, and having to repeatedly code these steps can become overwhelming. Spring Python's DatabaseTemplate lets us just inject the query string and and a row mapper to reduce the total amount of code that we need to write.

  3. We need a slightly different setup than before.

    """One time setup""" from springpython.database.core import * from springpython.database.factory import * connectionFactory = MySQLConnectionFactory(username="me", password="secret", hostname="localhost", db="springpython")

  4. We also need to define a mapping to generate our TvShow objects.

    class TvShowMapper(RowMapper): def map_row(self, row, metadata=None): return TvShow(title=row[0], airDate=row[1], episodeNumber=row[2], writer=row[3])

  5. With all this setup, we can now create an instance of DatabaseTemplate and use it to execute the same query with a much lower footprint.

    dt = DatabaseTemplate(connectionFactory) """Repeated for each query""" results = dt.query("""select title, air_date, episode_number, writer from tv_shows where name = %s""", ("Monty Python",), TvShowMapper())

This example shows how we can replace 19 lines of code with a single statement using Spring Python's template solution.

Object Relational Mappers (ORMs) have sprung up in response to the low level nature of ANSI SQL's protocol. Many applications have simple object persistence requirements and many of us would prefer working on code, and not database design. By having a tool to help do the schema management work, these ORMs have been a great productivity boost.

But they are not necessarily the answer for every use case. Some queries are very complex and involve looking up information spread between many tables, or involve making complex calculations and involve decoding specific values. Also, many legacy systems are denormalized and don't fit the paradigm that ORMs were originally designed to handle. The complexity of these queries can require working around, or even against, the ORM-based solutions, making them not worth the effort.

To alleviate the frustration of working with SQL, Spring Python's DatabaseTemplate greatly simplifies writing SQL, while giving you complete freedom in mapping the results into objects, dictionaries, and tuples. DatabaseTemplate can easily augment your application, whether or not you are already using an ORM. That way, simple object persistence can be managed with ORM, while complex queries can be handed over to Spring Python's DatabaseTemplate, resulting in a nice blend of productive, functional code.

Other templates, such as TransactionTemplate, relieve you of the burden of dealing with the low level idioms needed to code transactions that makes them challenging to incorporate correctly. Later in this book, we will learn how easy it is to add transactions to our code both programmatically and declaratively.

Applying the services you need and abstracting away low level APIs is a key part of the Spring way and lets us focus our time and effort on our customer's business requirements instead of our own technical ones.

By using the various components we just looked at, it isn't too hard to develop a simple Pyro service that serves up TV shows from a relational database.

from springpython.database.factory import * from springpython.config import * from springpython.remoting.pyro import * class TvShowMapper(RowMapper): def map_row(self, row, metadata=None): return (title=row[0], airDate=row[1], episodeNumber=row[2], writer=row[3]) class TvShowService(object): def __init__(self): self.connFactory = MySQLConnectionFactory(username="me", password="secret", hostname="localhost", db="springpython") self.dt = DatabaseTemplate(connFactory) def get_tv_shows(self): return dt.query("""select title, air_date, episode_number, writer from tv_shows where name = %s""", ("Monty Python",), TvShowMapper()) class TvShowContainer(PythonConfig): def __init__(self): super(TvShowContainer, self).__init__() @Object(lazy_init=True) def web_server(self): return PyroServiceExporter(service=TvShowService(), service_name="tvshows", service_port=9000) @Object(lazy_init=True) def web_client(self): myService = PyroProxyFactory() myService.service_url="PYROLOC://localhost:9000/tvshows" return myService if __name__ == "__main__": container = ApplicationContext(TvShowContainer()) container.get_object("web_server")

By querying the database for TV shows and serving it up through Pyro, this block of code demonstrates how easy it is to use these powerful modules without mixing them together. It is much easier to maintain software over time when things are kept simple and separated.

We just took a quick walk through SQL and Pyro and examined their low level APIs. Many low level APIs require a certain sequence of steps to properly utilize them. We just looked at a SQL query. The need for templates also exists with database transactions and LDAP calls. By capturing the flow of the API in a Spring Python template and allowing you to insert your custom code, you can get out of writing plumbing code and instead work on your application's business logic.

Spring Python 1.1 Create powerful and versatile Spring Python applications using pragmatic libraries and useful abstractions
Published: May 2010
eBook Price: $26.99
Book Price: $44.99
See more
Select your format and quantity:
        Read more about this book      

Spring Python for Java developers

Java developers often seek ways to increase productivity. With the incredible growth of alternative languages on the Java Virtual Machine (JVM), it is no wonder developers are looking into Jython (http://www.jython.org) as an alternative way to write scripts, segments, and subsystems. While it's convenient to use the Java libraries you already know, it can sometimes be rough interacting with the Java idioms of the library.

Spring Python is written in pure Python, which makes it easy to use inside Jython as well. You may find it easier and more appealing to utilize the pythonic APIs of Spring Python rather than the Java idioms of the Spring Framework. The choice ultimately is yours, and it's not an either/or decision; you can use both libraries in both your Java and Python segments.

The following diagram shows a combination of Python, Jython, and pure Java as a stack.

With Spring Python, it's easy to mix Java and Python together. Let's code a simple example, where we write a Jython client that talks to the TV service shown in the previous section. By reusing that code, we can easily code a client. To really show the power of Python/Jython/Java integration, let's expose our Jython client to a pure Java consumer.

  1. To begin, we need a pure Java interface that our Jython code can extend.

    import org.python.core.PyList;

    public interface JavaTvShowService {

    public PyList getTvShows();
    }

  2. Next, we write our Jython class to extend this interface.

    class JythonTvShowService(JavaTvShowService):
    def __init__(self):
    self.container = ApplicationContext(TvShowContainer())
    self.client = container.get_object("web_client")

    def getTvShows(self):
    return self.client.get_tv_shows()

  3. For Java clients to call Jython, we need to create a factory that creates an embedded Jython interpreter.

    import org.python.core.PyObject;
    import org.python.util.PythonInterpreter;

    public class TvShowServiceFactory {

    private PyObject clazz;

    public TvShowServiceFactory() {
    PythonInterpreter interp = new PythonInterpreter();
    interp.exec("import JythonTvShowService");
    clazz = interp.get("JythonTvShowService");
    }
    public JavaTvShowService createTvShowService() {
    PyObject tvShowService = clazz.__call__();
    return (JavaTvShowService)
    tvShowService.__tojava__(JavaTvShowService.class);
    }
    }

  4. Finally, we can write a main function that invokes the factory first, and then the JavaTvShowService.

    public class Main {
    public static void main(String[] args) {
    TvShowServiceFactory factory =
    new TvShowServiceFactory();
    JavaTvShowService service =
    factory.createTvShowService();
    PyList tvShows = service.getTvShows();
    for (int i = 0; i < tvShows.__len__(); i++) {
    PyObject obj = tvShows.__getitem__(i);
    PyTuple tvShow =
    (PyTuple)obj.__tojava__(PyTuple.class);
    System.out.println("Tv show title=" + tvShow.get(0) +
    " airDate=" + tvShow.get(1) +
    " episode=" + tvShow.get(2) +
    " writer=" + tvShow.get(3));
    }
    }
    }

We defined an interface, providing a good boundary to code both Java consumers and Jython services against. Our Jython class extends the interface and when created, creates an IoC container which requests a web_client object. This is our PyroProxyFactory that uses Pyro to call our pure Python service over the wire. By implementing the interface, we conveniently expose our remote procedure call to the Java consumers. Our Java app needs a factory class to create a Jython interpreter which in turn creates an instance of our Jython class. We use this in our application main to get an instance of our TV service. Using the service, we call the exposed method which makes our Pyro remote call. We iterate over the received list and extract a tuple in order to print out results.

After taking a glance at how to expose a pure Python service to a pure Java consumer, the options from here are endless. We could use Spring Java's RmiServiceExporter or HessianServiceExporter to expose our Python service to other protocols. This service could be integrated into a Spring Integration workflow or made part of a Spring Batch job. There really is no limit.

We have already looked at how easy it is to expose Python services to Java consumers. If you are already familiar with Spring Java, hopefully as you read this book, you will notice that the Spring way works not only in Java but in Python as well. Spring Python uses the same concepts as Spring Java, shares some class names with Spring Java, and even has an XML parser that can read Spring Java's format. All of these things increase the ability to rewrite some parts in Python while making small changes in the configuration files. All of these aspects make it easier to incrementally move our application to the sweet spot we need for improved productivity.

Extending Spring Python

Spring Python provides easy access to services, libraries, and APIs through its neatly segmented set of modules. Spring Python's flexibility is due to its modular nature. Providing you with a small set of blocks that are easy to combine is much more reusable than a monolithic set of classes to extend. These techniques open the door to easily integrating with current technologies and future ones as well.

In this article, we have already looked at various features, including remoting, DatabaseTemplate, and integrating Python with Java. As we explore the other features of Spring Python, I hope you can realize that using the Spring way of writing useful abstractions and delegating object creation to the Spring Python container makes it easy to write more modules that aren't part of this project yet.

And as your needs grow, this project will grow as well. Spring Python makes it easy to code your own templates and modules. You can code and inject your custom services just as easily as Spring Python's pre-built ones. If you have ideas for new features that you think belong in Spring Python, you can visit the website at http://springpython.webfactional.com to find out how to submit ideas, patches, and perhaps join the team to help grow Spring Python.

Installing Spring Python

Spring Python is easy to install. It comes with two installable tar balls. One is the core library itself. The other is a set of samples you can optionally install to help get a better understanding of Spring Python. As it is written in pure Python, the installed files are the source code as well, so you can see how Spring Python works.

This installation section does NOT show how to install all the parts needed to develop patches for the Spring Python project. For more information on setting up a developer's environment, please join the Spring Python mailing list at http://lists.springsource.com/listmanager/listinfo/springpython-users where you can ask about current development requirements.

Setting up an environment for Spring Python

Installing Spring Python currently requires Python 2.4, 2.5, or 2.6. It can also be run on Jython 2.5. At the time of this writing, it hasn't been extended to support Python 3 due to lack of backwards compatibility and immaturity. However, as Python 3 gains acceptance in the user community, Spring Python will move to support it as well.

Spring Python makes it easier to integrate with certain 3rd party libraries. Installation of those 3rd party libraries is not covered in this book. For example, to write queries against an Oracle database, you need to install the cxora package.

Installing from a pre-built binary download

The binaries are hosted as tar balls by SpringSource, in the community section. They are non-OS specific and should work on any platform.

  1. Go to http://www.springsource.org/download/community. You can either fill out the registration information, or simply click on the link to take you to the download site
  2. Click on Spring Python to see the latest version:
  3. Download springpython-&ltrelease&gt.tar.gz to get the core library
  4. Unpack the tarball, and go to the directory containing setup.py
  5. Type the following command to install Spring Python
  6. Note: This step may require admin privileges!

    $ python setup.py install

  7. You should now be able to test the installation.

    $ python
    >>> import springpython
    >>> dir()
    ['__builtins__', '__doc__', '__name__', 'springpython']

Spring Python 1.1 Create powerful and versatile Spring Python applications using pragmatic libraries and useful abstractions
Published: May 2010
eBook Price: $26.99
Book Price: $44.99
See more
Select your format and quantity:
        Read more about this book      

Installing from source

Spring Python can be installed from source code like many other open source projects. The code is hosted on a subversion repository. The following steps will help you download the code and install it on your machine:

  1. Type the following command to checkout the latest trunk repository:

    $ svn checkout https://src.springframework.org/svn/
    se-springpython-py/trunk/springpython springpython

    This will create a local directory springpython containing the latest changes.

  2. Move in to the directory where build.py is located. This script serves as the key tool to build, package, and test Spring Python. Type the following command to generate an installable Spring Python package:

    $ ./build.py –package

  3. Move to target/artifacts, the directory containing the newly generated tar balls.
  4. Unpack the tar ball springpython-&ltrelease&gt.tar.gz, and go to the directory containing setup.py and type the following command to install Spring Python:
  5. Note: This step may require admin privileges!

    $ python setup.py install

  6. You should now be able to test the installation.

    $ python
    >>> import springpython
    >>> dir()
    ['__builtins__', '__doc__', '__name__', 'springpython']

  7. Type the following command to update your checkout.

    $ svn update /path/for/springpython

    .

  8. Repeat the steps with build.py, target/artifacts, and setup.py.

Official releases are found in the tags section of the subversion repository, adjacent to the trunk.

You can also visually inspect the code using SpringSource's Fisheye viewer at https://fisheye.springframework.org/browse/se-springpython-py. This provides a way to view the code, change sets, and change logs as well.

Spring Python community

Spring Python values its user community, and takes its cue on key features from user requests. Many of the features currently found in Spring Python were added based on user requests, submitted patches, and feedback.

Summary

We have taken a quick tour of the various parts of Spring Python. The examples showed examples of how Spring Python can make things easier for both Python and Java developers.

In this article, we learned that:

  • Spring Python has a non-invasive API that makes it easy to use other libraries without having to make major changes to your own code base
  • Spring Python has a container that decouples object creation from object usage to empower the developer
  • Spring Python provides the means to help professional Python developers by offering a non-invasive API to easily access advanced services
  • Spring Python offers professional Java developers an easy way to mix Python and Java together through the combination of Python/Jython/Java
  • Spring Python can be installed from both binary and source code
  • Spring Python is very extensible and easily lets us add new components
  • There is a user community where we can post questions, answers, ideas, and patches

Further resources on this subject:


About the Author :


Greg L. Turnquist

Greg has worked since 1997 as a software engineer at Harris Corporation, always seeking the right tool for the job. Since 2002, Greg has been part of the senior software team working on Harris' $3.5 billion FAA telco program, architecting mission-critical enterprise apps while managing a software team. He provides after hours support and 2nd-level engineering to support the nation-wide telco network and is no stranger to midnight failures and software triage. In 2010, Greg joined the SpringSource division of VMware.

Being a test-bitten script junky, Greg has used JUnit, TestNG, JMock, FEST, PyUnit, and pMock testing frameworks, along with other agile practices to produce top-quality code.

He has worked with Java, Spring, Spring Security, AspectJ, and Jython technologies and also developed sophisticated scripts for *nix and Windows platforms. Being a wiki evangelist, he also deployed a LAMP-based wiki website to provide finger-tip knowledge to users.

In 2006, Greg created the Spring Python project. The Spring Framework provided many useful features, and he wanted those same features available when working with Python.

Greg completed a master's degree in Computer Engineering at Auburn University, and lives in the United States with his family.

Books From Packt


Python Text Processing with NLTK 2.0 Cookbook
Python Text Processing with NLTK 2.0 Cookbook

MySQL for Python
MySQL for Python

Python 2.6 Text Processing Beginners Guide
Python 2.6 Text Processing Beginners Guide

Python Multimedia
Python Multimedia

Python Geo-Spatial Development
Python Geo-Spatial Development

wxPython 2.8 Application Development Cookbook
wxPython 2.8 Application Development Cookbook

Python Testing: Beginner's Guide
Python Testing: Beginner's Guide

Python 3 Object Oriented Programming
Python 3 Object Oriented Programming


Code Download and Errata
Packt Anytime, Anywhere
Register Books
Print Upgrades
eBook Downloads
Video Support
Contact Us
Awards Voting Nominations Previous Winners
Judges Open Source CMS Hall Of Fame CMS Most Promising Open Source Project Open Source E-Commerce Applications Open Source JavaScript Library Open Source Graphics Software
Resources
Open Source CMS Hall Of Fame CMS Most Promising Open Source Project Open Source E-Commerce Applications Open Source JavaScript Library Open Source Graphics Software