<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>learning python &#187; Uncategorized</title>
	<atom:link href="http://www.learningpython.com/category/uncategorized/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.learningpython.com</link>
	<description>one man's journey into python...</description>
	<lastBuildDate>Mon, 26 Apr 2010 01:21:51 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=abc</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Introducing Descriptors and Properties</title>
		<link>http://www.learningpython.com/2010/04/25/introducing-descriptors-and-properties/</link>
		<comments>http://www.learningpython.com/2010/04/25/introducing-descriptors-and-properties/#comments</comments>
		<pubDate>Mon, 26 Apr 2010 01:21:51 +0000</pubDate>
		<dc:creator>selsine</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[descriptors]]></category>
		<category><![CDATA[properties]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[Python Magazine]]></category>

		<guid isPermaLink="false">http://www.learningpython.com/?p=186</guid>
		<description><![CDATA[
			
				
			
		
Note: This article was first published the May 2008 issue of Python Magazine
Introducing Descriptors and Properties
Mark Mruss
New-style classes were introduced to Python with the release of Python 2.2. And with these new-style classes came descriptors and properties. This article will introduce the descriptor protocol, descriptors, and properties.
Introduction
New-style classes were introduced to Python with the release [...]]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style="float: right; margin-left: 10px;">
			<a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fwww.learningpython.com%2F2010%2F04%2F25%2Fintroducing-descriptors-and-properties%2F"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fwww.learningpython.com%2F2010%2F04%2F25%2Fintroducing-descriptors-and-properties%2F&amp;style=normal" height="61" width="50" /><br />
			</a>
		</div>
<p>Note: This article was first published the <a href="http://www.pythonmagazine.com/c/issue/view/69">May 2008</a> issue of <a href="http://www.pythonmagazine.com/">Python Magazine</a></p>
<p><strong>Introducing Descriptors and Properties</strong></p>
<p><strong>Mark Mruss</strong></p>
<p>New-style classes were introduced to Python with the release of Python 2.2. And with these new-style classes came descriptors and properties. This article will introduce the descriptor protocol, descriptors, and properties.</p>
<h2>Introduction</h2>
<p>New-style classes were introduced to Python with the release of Python 2.2.  A new-style class is any class that is derived from the <code>object</code> base class. New-style classes give Python programmers many new (and initially confusing) features. One such feature is the descriptor protocol, and more specifically descriptors themselves.</p>
<p>Descriptors give Python programmers the ability to easily and efficiently create &#8220;managed attributes&#8221;. Managed attributes can be thought of as attributes that are not accessed directly. Instead their access is &#8220;managed&#8221; by something else, generally a class or a function.</p>
<p>If you haven&#8217;t come across this before you are probably wondering why one would want to manage attribute access? One reason might be that you don&#8217;t want people to be able to delete the attribute. Another reason may be that you need to ensure that your attribute data is always valid. Or perhaps attribute <code>x</code> is based on attribute <code>y</code>, so every time the value of <code>y</code> changes you want to update the value of <code>x</code>.  From these few examples you can see the many possible cases where you might want to control access to certain attributes.</p>
<p>For those of you familiar with other programming languages, this type of access is often referred to as &#8220;getters and setters&#8221;.  In many language, implementing &#8220;getters and setters&#8221; means using private variables and public functions that get and set the variable&#8217;s value. Since Python doesn&#8217;t (really) have private variables, the descriptor protocol is basically a built-in and “Python-ic” way to way to achieve something similar.</p>
<p>This article will introduce you to the descriptor protocol, descriptors, and properties. It will focus on demonstrating how to use them to create managed attributes. Since the descriptor protocol requires new-style classes, all of the examples in this article require Python 2.2 or newer.</p>
<p><span id="more-186"></span></p>
<h2>A few definitions</h2>
<p>Before moving forward, it is important to understand a few related terms. These terms will introduce some basic concepts and help you follow along with the remainder of the article.</p>
<p><strong>descriptor protocol</strong> &#8211; The following three methods make up the descriptor protocol: <code>__get__</code>, <code>__set__</code>, and <code>__delete__</code>.</p>
<p><strong>descriptor</strong> &#8211; An &#8220;object attribute with <code>binding behavior</code>, one whose attribute access has been overridden by methods in the descriptor protocol.&#8221; <a href="http://docs.python.org/ref/descriptor-invocation.html">[1]</a> In other words an &#8220;attributes whose usage resembles attribute access, but whose implementation uses method calls.&#8221;<a href="http://www.python.org/download/releases/2.2/descrintro/#property">[2]</a></p>
<p><strong>data descriptor</strong> &#8211; A descriptor with the <code>__get__</code> and <code>__set__</code> methods of the descriptor protocol defined.</p>
<p><strong>non-data descriptor</strong> &#8211; A descriptor with only the <code>__get__</code>  method of the descriptor protocol defined. &#8220;Python methods (including staticmethod() and classmethod()) are implemented as non-data descriptors.&#8221; <a href="http://docs.python.org/ref/descriptor-invocation.html">[3]</a></p>
<p><strong>property</strong> &#8211; A built-in type that implements the descriptor protocol and allows you to easily create data descriptors.</p>
<p>Don&#8217;t worry if you don&#8217;t fully understand these definitions, the remainder of this article will hopefully clarify any confusion you have.</p>
<h2>The Descriptor Protocol</h2>
<p>Let&#8217;s take a closer look at the descriptor protocol and see how we can use it to create a descriptor.  As previously mentioned, the descriptor protocol is made up of three methods: <code>__get__</code>, <code>__set__</code>, and <code>__delete__</code>.  These methods have specific signatures and they are as follows, where <code>self</code> is the class that owns the methods:</p>
<div class="hl-surround" ><div class="hl-main"><pre><span class="hl-identifier">__get__</span><span class="hl-brackets">(</span><span class="hl-identifier">self</span><span class="hl-code">, </span><span class="hl-identifier">instance</span><span class="hl-code">, </span><span class="hl-identifier">owner</span><span class="hl-brackets">)
</span><span class="hl-identifier">__set__</span><span class="hl-brackets">(</span><span class="hl-identifier">self</span><span class="hl-code">, </span><span class="hl-identifier">instance</span><span class="hl-code">, </span><span class="hl-identifier">value</span><span class="hl-brackets">)
</span><span class="hl-identifier">__delete__</span><span class="hl-brackets">(</span><span class="hl-identifier">self</span><span class="hl-code">, </span><span class="hl-identifier">instance</span><span class="hl-brackets">)</span></pre></div></div>
<p>These three methods represent the three basic operations that you perform on attributes in general: querying the value of that attribute; assigning a value to it; and, (very rarely) deleting it. They work as follows:</p>
<ul>
<li>
The <code>__get__</code> method is called when the attributes value is being queried.  The <code>__get__</code> method should return the (computed) attribute value or raise an AttributeError exception.&#8221; <a href="http://docs.python.org/ref/descriptors.html">[4]</a> This is where access to the attribute&#8217;s value is managed.
</li>
<li>
The <code>__set__</code> method is used in the assignment operation. It is called when we want to set the attribute value. This is where you can control what values, or types of values are being assigned to your attribute.
</li>
<li>Finally, the <code>__delete__</code> method is called when we want to delete the attribute. Here you can (rarely) decide whether or not to delete the attribute.
</li>
</ul>
<p>There are also three different parameters passed to the three methods (excluding the standard <code>self</code> parameter for methods that belong to a class):</p>
<ul>
<li>
<code>owner</code> &#8211; This &#8220;is always the owner class.&#8221; <a href="http://docs.python.org/ref/descriptors.html">[5]</a> This means that it is the actual class, and not an instance of the class. So if the descriptor is in a class called <code>MyClass</code>, <code>owner</code> will be that class.
</li>
<li>
<code>instance</code> &#8211; An instance of class type <code>owner</code>. It is &#8220;the instance that the attribute was accessed through&#8221; <a href="http://docs.python.org/ref/descriptors.html">[6]</a>, or <code>None</code> if the attribute is being accessed through the class (<code>owner</code>) instead of an instance.
</li>
<li>
<code>value</code>- The value that the attribute is being set to.
</li>
</ul>
<p>This difference between <code>owner</code> and <code>instance</code> might be a bit confusing, so let&#8217;s look at a quick example. Let’s say we have a descriptor <code>my_descriptor</code> in the class <code>MyClass</code>, if we were to run the following code:</p>
<div class="hl-surround" ><div class="hl-main"><pre><span class="hl-identifier">my_class_instance</span><span class="hl-default"> = </span><span class="hl-identifier">MyClass</span><span class="hl-brackets">()
</span><span class="hl-reserved">print </span><span class="hl-identifier">my_class_instance</span><span class="hl-default">.</span><span class="hl-identifier">my_descriptor</span></pre></div></div>
<p>The second line queries the descriptors value and results in the <code>__get__</code> method being called with the <code>instance</code> parameter being <code>my_class_instance</code>. The <code>owner</code> parameter will be the <code>MyClass</code> class.</p>
<p><strong>Note:</strong> Notice that we treat the descriptor <code>my_descriptor</code> as though it is a normal attribute. We don&#8217;t call <code>print my_class_instance.my_descriptor.__get__(my_class, MyClass)</code>. This is what was meant by: &#8220;attributes whose usage resembles attribute access, but whose implementation uses method calls.&#8221;<a href="http://www.python.org/download/releases/2.2/descrintro/#property">[7]</a></p>
<p>If the following code were run:</p>
<div class="hl-surround" style="height:28px;"><div class="hl-main"><pre><span class="hl-reserved">print </span><span class="hl-identifier">MyClass</span><span class="hl-default">.</span><span class="hl-identifier">my_descriptor</span></pre></div></div>
<p>The <code>__get__</code> method will again be called. This time the <code>instance</code> parameter will be <code>None</code> and the <code>owner</code> parameter will be the <code>MyClass</code> class.</p>
<p><strong>Note:</strong> Only the <code>__get__</code> method has the <code>owner</code> parameter. This means that it is the only function in the descriptor protocol that can be accessed through the class. Setting and deleting the descriptor through the class actually changes <strong>what</strong> the variable is. For example, if we tried to assign the numeric value 2 to a descriptor variable using the class, we would not access the descriptors <code>__set__</code> method. Instead we would change the type of the variable from a descriptor to an integer with the value of 2.</p>
<h2>A Simple Descriptor Example</h2>
<p>A simple &#8220;transparent&#8221; descriptor example can be found in Listing 1. The first thing to notice in the code is that both the <code>SimpleDescriptor</code> and <code>MyClass</code> classes are &#8220;new-style&#8221; classes because they are derived from <code>object</code>. This is important because, as mentioned above, descriptors only work with &#8220;new-style&#8221; classes. The second point to notice is that the descriptor has class scope as opposed to instance scope. There are also two extra print statements included in the code. They are there to let us follow the execution a little more easily.</p>
<p><strong>Listing 1</strong></p>
<div class="hl-surround" ><div class="hl-main"><pre><span class="hl-reserved">class </span><span class="hl-identifier">SimpleDescriptor</span><span class="hl-brackets">(</span><span class="hl-identifier">object</span><span class="hl-brackets">)</span><span class="hl-default">:

    </span><span class="hl-reserved">def </span><span class="hl-identifier">__get__</span><span class="hl-brackets">(</span><span class="hl-identifier">self</span><span class="hl-code">, </span><span class="hl-identifier">instance</span><span class="hl-code">, </span><span class="hl-identifier">owner</span><span class="hl-brackets">)</span><span class="hl-default">:
        </span><span class="hl-comment"># Check if the value has been set
        </span><span class="hl-identifier">if </span><span class="hl-brackets">(</span><span class="hl-reserved">not </span><span class="hl-builtin">hasattr</span><span class="hl-brackets">(</span><span class="hl-identifier">self</span><span class="hl-code">, </span><span class="hl-quotes">&quot;</span><span class="hl-string">_value</span><span class="hl-quotes">&quot;</span><span class="hl-brackets">))</span><span class="hl-default">:
            </span><span class="hl-reserved">raise AttributeError
        print </span><span class="hl-quotes">&quot;</span><span class="hl-string">Getting value: %s</span><span class="hl-quotes">&quot;</span><span class="hl-default"> % </span><span class="hl-identifier">self</span><span class="hl-default">.</span><span class="hl-identifier">_value
        </span><span class="hl-reserved">return </span><span class="hl-identifier">self</span><span class="hl-default">.</span><span class="hl-identifier">_value

    </span><span class="hl-reserved">def </span><span class="hl-identifier">__set__</span><span class="hl-brackets">(</span><span class="hl-identifier">self</span><span class="hl-code">, </span><span class="hl-identifier">instance</span><span class="hl-code">, </span><span class="hl-identifier">value</span><span class="hl-brackets">)</span><span class="hl-default">:
        </span><span class="hl-reserved">print </span><span class="hl-quotes">&quot;</span><span class="hl-string">Setting to %s</span><span class="hl-quotes">&quot;</span><span class="hl-default"> % </span><span class="hl-identifier">value
        self</span><span class="hl-default">.</span><span class="hl-identifier">_value</span><span class="hl-default"> = </span><span class="hl-identifier">value

    </span><span class="hl-reserved">def </span><span class="hl-identifier">__delete__</span><span class="hl-brackets">(</span><span class="hl-identifier">self</span><span class="hl-code">, </span><span class="hl-identifier">instance</span><span class="hl-brackets">)</span><span class="hl-default">:
        </span><span class="hl-identifier">del</span><span class="hl-brackets">(</span><span class="hl-identifier">self</span><span class="hl-code">.</span><span class="hl-identifier">_value</span><span class="hl-brackets">)

</span><span class="hl-reserved">class </span><span class="hl-identifier">MyClass</span><span class="hl-brackets">(</span><span class="hl-identifier">object</span><span class="hl-brackets">)</span><span class="hl-default">:
    </span><span class="hl-identifier">my_value</span><span class="hl-default"> = </span><span class="hl-identifier">SimpleDescriptor</span><span class="hl-brackets">()</span></pre></div></div>
<p>Using Listing 1 to execute the following code:</p>
<div class="hl-surround" ><div class="hl-main"><pre><span class="hl-identifier">my_instance</span><span class="hl-default"> = </span><span class="hl-identifier">MyClass</span><span class="hl-brackets">()
</span><span class="hl-identifier">my_instance</span><span class="hl-default">.</span><span class="hl-identifier">my_value</span><span class="hl-default"> = </span><span class="hl-number">416
</span><span class="hl-reserved">print </span><span class="hl-identifier">my_instance</span><span class="hl-default">.</span><span class="hl-identifier">my_value</span></pre></div></div>
<p>The output would be the following:</p>
<div class="hl-surround" ><div class="hl-main"><pre><span class="hl-identifier">Setting to </span><span class="hl-number">416
</span><span class="hl-identifier">Getting value</span><span class="hl-default">: </span><span class="hl-number">416
416</span></pre></div></div>
<p>As you can see the second line (<code>my_instance.data_descriptor = 416</code>) calls the <code>__set__</code> method and sets the _value attribute. When we call <code>print my_instance.data_descriptor</code> the <code>__get__</code>, method is called and the <code>_value</code> attribute is returned.</p>
<h2>The Problem with the Simple Example</h2>
<p>The previous example may look like a perfectly good descriptor, but there is something wrong with it. Take a look at what happens when we runs this new code:</p>
<div class="hl-surround" ><div class="hl-main"><pre><span class="hl-identifier">my_instance</span><span class="hl-default"> = </span><span class="hl-identifier">MyClass</span><span class="hl-brackets">() </span><span class="hl-comment">#Create the first instance
</span><span class="hl-identifier">my_instance</span><span class="hl-default">.</span><span class="hl-identifier">my_value</span><span class="hl-default"> = </span><span class="hl-number">416 </span><span class="hl-comment">#Set its' value
</span><span class="hl-identifier">my_second_instance</span><span class="hl-default"> = </span><span class="hl-identifier">MyClass</span><span class="hl-brackets">() </span><span class="hl-comment">#Create the second instance
</span><span class="hl-identifier">my_second_instance</span><span class="hl-default">.</span><span class="hl-identifier">my_value</span><span class="hl-default"> = </span><span class="hl-number">204 </span><span class="hl-comment">#Set its' value
</span><span class="hl-reserved">print </span><span class="hl-identifier">my_instance</span><span class="hl-default">.</span><span class="hl-identifier">my_value </span><span class="hl-comment">#What was the fist instance's value?</span></pre></div></div>
<p>We get the following output:</p>
<div class="hl-surround" ><div class="hl-main"><pre><span class="hl-identifier">Setting to </span><span class="hl-number">416
</span><span class="hl-identifier">Setting to </span><span class="hl-number">204
</span><span class="hl-identifier">Getting value</span><span class="hl-default">: </span><span class="hl-number">204
204</span></pre></div></div>
<p>Notice that when we set the second instance&#8217;s <code>my_value</code> descriptor to be 204, we are also setting the first instances. This is because <code>my_value</code> has class scope, so both instances (and the class itself) share the same instance of the <code>SimpleDescriptor</code> class. Since <code>SimpleDescriptor</code> only stores one value, they all actually share the same value. We will get the same results if we check what the classes value of <code>my_value</code> is:</p>
<div class="hl-surround" ><div class="hl-main"><pre><span class="hl-identifier">my_instance</span><span class="hl-default"> = </span><span class="hl-identifier">MyClass</span><span class="hl-brackets">() </span><span class="hl-comment">#Create the first instance
</span><span class="hl-identifier">my_instance</span><span class="hl-default">.</span><span class="hl-identifier">my_value</span><span class="hl-default"> = </span><span class="hl-number">416 </span><span class="hl-comment">#Set its' value
</span><span class="hl-identifier">my_second_instance</span><span class="hl-default"> = </span><span class="hl-identifier">MyClass</span><span class="hl-brackets">() </span><span class="hl-comment">#Create the second instance
</span><span class="hl-identifier">my_second_instance</span><span class="hl-default">.</span><span class="hl-identifier">my_value</span><span class="hl-default"> = </span><span class="hl-number">204 </span><span class="hl-comment">#Set its' value
</span><span class="hl-reserved">print </span><span class="hl-identifier">MyClass</span><span class="hl-default">.</span><span class="hl-identifier">my_value </span><span class="hl-comment">#What's the classes value?</span></pre></div></div>
<p>We get the following results:</p>
<div class="hl-surround" ><div class="hl-main"><pre><span class="hl-identifier">Setting to </span><span class="hl-number">416
</span><span class="hl-identifier">Setting to </span><span class="hl-number">204
</span><span class="hl-identifier">Getting value</span><span class="hl-default">: </span><span class="hl-number">204
204</span></pre></div></div>
<p>In the last line of the code (<code>print MyClass.my_value #What's the classes value?</code>) we simply use the class (ignoring both instances) in order to get the value of <code>my_data</code>. This will be an instance where the <code>__get__</code> function will be called with the <code>instance</code> parameter set to <code>None</code>.</p>
<p><strong>Note:</strong> This is not a problem if you want to share the value across all instances.</p>
<h2>The Solution to the Problem</h2>
<p>In order to get around this issue, you have to remember that if you want values unique to each instance your descriptors must store values that are unique to each instance. This can be in the instance itself, in dictionary in the descriptor, or perhaps in a text file. Just make sure that the value is unique to each instance. Though it seems like a simple solution, in practice a suitable solution for all cases is difficult to implement. As a result you should probably pick a specific implementation for your specific situations.</p>
<p>Using each instance as a key, one can store the value in a dictionary in the descriptor itself. The problem with this solution should be obvious to programmers familiar with Python dictionaries: only immutable types can be used as keys. This is fine if you know what object you are working with, but what about in the future when you want to add a descriptor to your sub-classed list?</p>
<p>Another solution is to store the value in the instance itself. You can do this by easily adding the value to the instance&#8217;s <code>__dict__</code>. The limitation is that the descriptor need to be given a suitable key so that there is no collision with anything already in the instance&#8217;s <code>__dict__</code>.</p>
<p>Listing 2 shows a solution to the problem from the previous section where the value is stored in the instance&#8217;s <code>__dict__</code>. Values are indexed using a key name provided during the creation of the descriptor.  Aside from where we store the value, there is little difference between Listing 1 and Listing 2.  Notice that the value name is a converted into a string. This is done to ensure that it can be used as a key.</p>
<p><strong>Listing 2</strong></p>
<div class="hl-surround" style="height:280px;"><div class="hl-main"><pre><span class="hl-reserved">class </span><span class="hl-identifier">FixedDescriptor</span><span class="hl-brackets">(</span><span class="hl-identifier">object</span><span class="hl-brackets">)</span><span class="hl-default">:

</span><span class="hl-reserved">def </span><span class="hl-identifier">__init__</span><span class="hl-brackets">(</span><span class="hl-identifier">self</span><span class="hl-code">, </span><span class="hl-identifier">value_name</span><span class="hl-brackets">)</span><span class="hl-default">:
    </span><span class="hl-identifier">self</span><span class="hl-default">.</span><span class="hl-identifier">value_name</span><span class="hl-default"> = </span><span class="hl-builtin">str</span><span class="hl-brackets">(</span><span class="hl-identifier">value_name</span><span class="hl-brackets">)

</span><span class="hl-reserved">def </span><span class="hl-identifier">__get__</span><span class="hl-brackets">(</span><span class="hl-identifier">self</span><span class="hl-code">, </span><span class="hl-identifier">instance</span><span class="hl-code">, </span><span class="hl-identifier">owner</span><span class="hl-brackets">)</span><span class="hl-default">:
    </span><span class="hl-identifier">if </span><span class="hl-brackets">(</span><span class="hl-identifier">instance </span><span class="hl-reserved">is None</span><span class="hl-brackets">)</span><span class="hl-default">:
        </span><span class="hl-reserved">raise AttributeError
    </span><span class="hl-identifier">elif </span><span class="hl-brackets">(</span><span class="hl-reserved">not </span><span class="hl-identifier">instance</span><span class="hl-code">.</span><span class="hl-identifier">__dict__</span><span class="hl-code">.</span><span class="hl-identifier">has_key</span><span class="hl-brackets">(</span><span class="hl-identifier">self</span><span class="hl-code">.</span><span class="hl-identifier">value_name</span><span class="hl-brackets">))</span><span class="hl-default">:
        </span><span class="hl-reserved">raise AttributeError
    return </span><span class="hl-identifier">instance</span><span class="hl-default">.</span><span class="hl-identifier">__dict__</span><span class="hl-brackets">[</span><span class="hl-identifier">self</span><span class="hl-code">.</span><span class="hl-identifier">value_name</span><span class="hl-brackets">]

    </span><span class="hl-reserved">def </span><span class="hl-identifier">__set__</span><span class="hl-brackets">(</span><span class="hl-identifier">self</span><span class="hl-code">, </span><span class="hl-identifier">instance</span><span class="hl-code">, </span><span class="hl-identifier">value</span><span class="hl-brackets">)</span><span class="hl-default">:
        </span><span class="hl-reserved">print </span><span class="hl-quotes">&quot;</span><span class="hl-string">Setting to %s</span><span class="hl-quotes">&quot;</span><span class="hl-default"> % </span><span class="hl-identifier">value
        instance</span><span class="hl-default">.</span><span class="hl-identifier">__dict__</span><span class="hl-brackets">[</span><span class="hl-identifier">self</span><span class="hl-code">.</span><span class="hl-identifier">value_name</span><span class="hl-brackets">]</span><span class="hl-default"> = </span><span class="hl-identifier">value

    </span><span class="hl-reserved">def </span><span class="hl-identifier">__delete__</span><span class="hl-brackets">(</span><span class="hl-identifier">self</span><span class="hl-code">, </span><span class="hl-identifier">instance</span><span class="hl-brackets">)</span><span class="hl-default">:
        </span><span class="hl-identifier">if </span><span class="hl-brackets">(</span><span class="hl-identifier">instance</span><span class="hl-code">.</span><span class="hl-identifier">__dict__</span><span class="hl-code">.</span><span class="hl-identifier">has_key</span><span class="hl-brackets">(</span><span class="hl-identifier">self</span><span class="hl-code">.</span><span class="hl-identifier">value_name</span><span class="hl-brackets">))</span><span class="hl-default">:
            </span><span class="hl-identifier">del</span><span class="hl-brackets">(</span><span class="hl-identifier">instance</span><span class="hl-code">.</span><span class="hl-identifier">__dict__</span><span class="hl-brackets">[</span><span class="hl-identifier">self</span><span class="hl-code">.</span><span class="hl-identifier">value_name</span><span class="hl-brackets">])


</span><span class="hl-reserved">class </span><span class="hl-identifier">MyClass</span><span class="hl-brackets">(</span><span class="hl-identifier">object</span><span class="hl-brackets">)</span><span class="hl-default">:
    </span><span class="hl-identifier">my_value</span><span class="hl-default"> = </span><span class="hl-identifier">FixedDescriptor</span><span class="hl-brackets">(</span><span class="hl-quotes">&quot;</span><span class="hl-string">__value</span><span class="hl-quotes">&quot;</span><span class="hl-brackets">)</span></pre></div></div>
<p>The major usage difference between Listing 1 and Listing 2 is the fact that the <code>__get__</code> method no longer works at class level; it only works at instance level. This should be obvious since this solution stores the value in the instance.  If there is no instance, we have nowhere to store the value!  If you attempt to access the descriptor at class level (the first if statement) an attribute error will be raised:</p>
<div class="hl-surround" ><div class="hl-main"><pre><span class="hl-reserved">def </span><span class="hl-identifier">__get__</span><span class="hl-brackets">(</span><span class="hl-identifier">self</span><span class="hl-code">, </span><span class="hl-identifier">instance</span><span class="hl-code">, </span><span class="hl-identifier">owner</span><span class="hl-brackets">)</span><span class="hl-default">:
    </span><span class="hl-identifier">if </span><span class="hl-brackets">(</span><span class="hl-identifier">instance </span><span class="hl-reserved">is None</span><span class="hl-brackets">)</span><span class="hl-default">:
        </span><span class="hl-reserved">raise AttributeError
    </span><span class="hl-identifier">elif </span><span class="hl-brackets">(</span><span class="hl-reserved">not </span><span class="hl-identifier">instance</span><span class="hl-code">.</span><span class="hl-identifier">__dict__</span><span class="hl-code">.</span><span class="hl-identifier">has_key</span><span class="hl-brackets">(</span><span class="hl-identifier">self</span><span class="hl-code">.</span><span class="hl-identifier">value_name</span><span class="hl-brackets">))</span><span class="hl-default">:
        </span><span class="hl-reserved">raise AttributeError
    return </span><span class="hl-identifier">instance</span><span class="hl-default">.</span><span class="hl-identifier">__dict__</span><span class="hl-brackets">[</span><span class="hl-identifier">self</span><span class="hl-code">.</span><span class="hl-identifier">value_name</span><span class="hl-brackets">]</span></pre></div></div>
<h2>Easy Data Descriptors with Properties</h2>
<p>The descriptor provided in Listing 2 will work for many situations but for my money the easiest way to implement data descriptors is to use the <code>property</code> type. I would recommend using it unless you need the same descriptor across many different classes or attributes (i.e. for type validation). Properties can be thought of as a simple and easy way to create data descriptors. The <code>property</code> type implements the descriptor protocol and gets around the problem of where to store the descriptor value in an easy way: it lets the class that created the descriptor deal with it.</p>
<p>The full signature of the <code>property</code> function is as follows:</p>
<div class="hl-surround" style="height:28px;"><div class="hl-main"><pre><span class="hl-builtin">property</span><span class="hl-brackets">(</span><span class="hl-identifier">fget</span><span class="hl-code">=</span><span class="hl-reserved">None</span><span class="hl-code">, </span><span class="hl-identifier">fset</span><span class="hl-code">=</span><span class="hl-reserved">None</span><span class="hl-code">, </span><span class="hl-identifier">fdel</span><span class="hl-code">=</span><span class="hl-reserved">None</span><span class="hl-code">, </span><span class="hl-identifier">doc</span><span class="hl-code">=</span><span class="hl-reserved">None</span><span class="hl-brackets">)</span></pre></div></div>
<p>Where <code>fget</code>, <code>fset</code>, <code>fdel</code> are methods that will be called when the <code>__get__</code>, <code>__set__</code>, and <code>__del__</code> members of the descriptor protocol are called. The <code>doc</code> parameter is a string that will be used as the docstring for the descriptor.  If the <code>doc</code> parameter is not specified, the docstring of the <code>fget</code> method is used.</p>
<p>The signature of the <code>fget</code>, <code>fset</code>, <code>fdel</code> functions are as follows:</p>
<div class="hl-surround" ><div class="hl-main"><pre><span class="hl-identifier">fget</span><span class="hl-brackets">(</span><span class="hl-identifier">instance</span><span class="hl-brackets">)
</span><span class="hl-identifier">fset</span><span class="hl-brackets">(</span><span class="hl-identifier">instance</span><span class="hl-code">, </span><span class="hl-identifier">value</span><span class="hl-brackets">)
</span><span class="hl-identifier">fdel</span><span class="hl-brackets">(</span><span class="hl-identifier">instance</span><span class="hl-brackets">)</span></pre></div></div>
<p>In the three signatures, <code>instance</code> is a reference to the object that owns the property attribute. This is the same instance that gets passed to the descriptor protocol.  Since <code>instance</code> is the first parameter of each method, these are, for all intents and purposes, member methods of a class. The <code>value</code> parameter is the same as the <code>value</code> parameter that is passed to the <code>__set__</code> method. It is what we are setting the attribute to.</p>
<p>The basic way to implement properties can be seen in Listing 3. As you can see, what we do for a property is very similar to what we did for our initial descriptor in Listing 1. We set up the three functions necessary for the descriptor protocol, and then use them to create our property attribute.  Creating the property is very simple:</p>
<p><strong>Listing 3</strong></p>
<div class="hl-surround" style="height:280px;"><div class="hl-main"><pre><span class="hl-reserved">class </span><span class="hl-identifier">MyClass</span><span class="hl-brackets">(</span><span class="hl-identifier">object</span><span class="hl-brackets">)</span><span class="hl-default">:
    </span><span class="hl-comment">#Create the fget, fset, and fdel methods
    </span><span class="hl-reserved">def </span><span class="hl-identifier">__get_value</span><span class="hl-brackets">(</span><span class="hl-identifier">self</span><span class="hl-brackets">)</span><span class="hl-default">:
        </span><span class="hl-reserved">print </span><span class="hl-quotes">&quot;</span><span class="hl-string">Getting value: %s</span><span class="hl-quotes">&quot;</span><span class="hl-default"> % </span><span class="hl-identifier">self</span><span class="hl-default">.</span><span class="hl-identifier">__value
        </span><span class="hl-reserved">return </span><span class="hl-identifier">self</span><span class="hl-default">.</span><span class="hl-identifier">__value

    </span><span class="hl-reserved">def </span><span class="hl-identifier">__set_value</span><span class="hl-brackets">(</span><span class="hl-identifier">self</span><span class="hl-code">, </span><span class="hl-identifier">value</span><span class="hl-brackets">)</span><span class="hl-default">:
        </span><span class="hl-reserved">print </span><span class="hl-quotes">&quot;</span><span class="hl-string">Setting to %s</span><span class="hl-quotes">&quot;</span><span class="hl-default"> % </span><span class="hl-identifier">value
        self</span><span class="hl-default">.</span><span class="hl-identifier">__value</span><span class="hl-default"> = </span><span class="hl-identifier">value

    </span><span class="hl-reserved">def </span><span class="hl-identifier">__del_value</span><span class="hl-brackets">(</span><span class="hl-identifier">self</span><span class="hl-brackets">)</span><span class="hl-default">:
        </span><span class="hl-identifier">del</span><span class="hl-brackets">(</span><span class="hl-identifier">self</span><span class="hl-code">.</span><span class="hl-identifier">__value</span><span class="hl-brackets">)

    </span><span class="hl-comment">#Create the property
    </span><span class="hl-identifier">my_value</span><span class="hl-default"> = </span><span class="hl-builtin">property</span><span class="hl-brackets">(</span><span class="hl-identifier">__get_value</span><span class="hl-code">
            , </span><span class="hl-identifier">__set_value</span><span class="hl-code">
            , </span><span class="hl-identifier">__del_value</span><span class="hl-code">
            , </span><span class="hl-quotes">&quot;</span><span class="hl-string">This is my property</span><span class="hl-quotes">&quot;</span><span class="hl-brackets">)

    </span><span class="hl-reserved">def </span><span class="hl-identifier">__init__</span><span class="hl-brackets">(</span><span class="hl-identifier">self</span><span class="hl-code">, </span><span class="hl-identifier">value</span><span class="hl-code">=</span><span class="hl-number">0</span><span class="hl-brackets">)</span><span class="hl-default">:
        </span><span class="hl-identifier">self</span><span class="hl-default">.</span><span class="hl-identifier">my_value</span><span class="hl-default"> = </span><span class="hl-identifier">value</span></pre></div></div>
<div class="hl-surround" ><div class="hl-main"><pre><span class="hl-identifier">my_value</span><span class="hl-default"> = </span><span class="hl-builtin">property</span><span class="hl-brackets">(</span><span class="hl-identifier">__get_value</span><span class="hl-code">
        , </span><span class="hl-identifier">__set_value</span><span class="hl-code">
        , </span><span class="hl-identifier">__del_value</span><span class="hl-code">
        , </span><span class="hl-quotes">&quot;</span><span class="hl-string">This is my property</span><span class="hl-quotes">&quot;</span><span class="hl-brackets">)</span></pre></div></div>
<h2>Make Data Attributes Data-Descriptors</h2>
<p>A common reason to use descriptors is to create read-only attributes. This means allowing callers to get (or access) an attribute&#8217;s value, but not allowing them to set its&#8217; value. At first glance it seems as though one can accomplish this by using descriptors with only the <code>__get__</code> method defined, i.e. a &#8220;non-data descriptor&#8221;.</p>
<p>While this seems to create a read-only descriptor attribute, it actually does nothing of the sort. Instead of using the descriptor&#8217;s <code>__set__</code> function for the assignment operation (since no <code>__set__</code> function is defined), the default Python assignment operation is used. This means that instead of stopping the assignment operation, a new attribute will be created in the instance (remember that descriptors have class scope) having the same name as the descriptor attribute and taking precedence in future operations.</p>
<p>This may be a bit confusing so let&#8217;s look at the example in Listing 4. It&#8217;s very much like our previous descriptor examples except it does not specify the <code>__set__</code> and <code>__del__</code> functions. Let’s look at what happens when we try to use this as though it were a read-only attribute:</p>
<p><strong>Listing 4</strong></p>
<div class="hl-surround" ><div class="hl-main"><pre><span class="hl-reserved">class </span><span class="hl-identifier">WonkyDescriptor</span><span class="hl-brackets">(</span><span class="hl-identifier">object</span><span class="hl-brackets">)</span><span class="hl-default">:
    </span><span class="hl-quotes">&quot;&quot;&quot;</span><span class="hl-string">This Descriptor isn't read only</span><span class="hl-quotes">&quot;&quot;&quot;
    </span><span class="hl-reserved">def </span><span class="hl-identifier">__init__</span><span class="hl-brackets">(</span><span class="hl-identifier">self</span><span class="hl-code">, </span><span class="hl-identifier">value_name</span><span class="hl-brackets">)</span><span class="hl-default">:
        </span><span class="hl-identifier">self</span><span class="hl-default">.</span><span class="hl-identifier">value_name</span><span class="hl-default"> = </span><span class="hl-builtin">str</span><span class="hl-brackets">(</span><span class="hl-identifier">value_name</span><span class="hl-brackets">)

    </span><span class="hl-reserved">def </span><span class="hl-identifier">__get__</span><span class="hl-brackets">(</span><span class="hl-identifier">self</span><span class="hl-code">, </span><span class="hl-identifier">instance</span><span class="hl-code">, </span><span class="hl-identifier">owner</span><span class="hl-brackets">)</span><span class="hl-default">:
        </span><span class="hl-identifier">if </span><span class="hl-brackets">(</span><span class="hl-identifier">instance </span><span class="hl-reserved">is None</span><span class="hl-brackets">)</span><span class="hl-default">:
            </span><span class="hl-reserved">raise AttributeError
        </span><span class="hl-identifier">elif </span><span class="hl-brackets">(</span><span class="hl-reserved">not </span><span class="hl-identifier">instance</span><span class="hl-code">.</span><span class="hl-identifier">__dict__</span><span class="hl-code">.</span><span class="hl-identifier">has_key</span><span class="hl-brackets">(</span><span class="hl-identifier">self</span><span class="hl-code">.</span><span class="hl-identifier">value_name</span><span class="hl-brackets">))</span><span class="hl-default">:
            </span><span class="hl-reserved">raise AttributeError
        print </span><span class="hl-quotes">&quot;</span><span class="hl-string">Getting a value</span><span class="hl-quotes">&quot;
        </span><span class="hl-reserved">return </span><span class="hl-identifier">instance</span><span class="hl-default">.</span><span class="hl-identifier">__dict__</span><span class="hl-brackets">[</span><span class="hl-identifier">self</span><span class="hl-code">.</span><span class="hl-identifier">value_name</span><span class="hl-brackets">]

</span><span class="hl-reserved">class </span><span class="hl-identifier">MyClass</span><span class="hl-brackets">(</span><span class="hl-identifier">object</span><span class="hl-brackets">)</span><span class="hl-default">:

    </span><span class="hl-identifier">my_value</span><span class="hl-default"> = </span><span class="hl-identifier">WonkyDescriptor</span><span class="hl-brackets">(</span><span class="hl-quotes">&quot;</span><span class="hl-string">_value</span><span class="hl-quotes">&quot;</span><span class="hl-brackets">)

    </span><span class="hl-reserved">def </span><span class="hl-identifier">__init__</span><span class="hl-brackets">(</span><span class="hl-identifier">self</span><span class="hl-code">, </span><span class="hl-identifier">value</span><span class="hl-brackets">)</span><span class="hl-default">:
        </span><span class="hl-comment">#initial value
        </span><span class="hl-identifier">self</span><span class="hl-default">.</span><span class="hl-identifier">_value</span><span class="hl-default"> = </span><span class="hl-identifier">value</span></pre></div></div>
<div class="hl-surround" ><div class="hl-main"><pre><span class="hl-identifier">my_instance</span><span class="hl-default"> = </span><span class="hl-identifier">MyClass</span><span class="hl-brackets">(</span><span class="hl-number">23</span><span class="hl-brackets">) </span><span class="hl-comment">#Create the first instance
</span><span class="hl-reserved">print </span><span class="hl-identifier">my_instance</span><span class="hl-default">.</span><span class="hl-identifier">my_value
my_instance</span><span class="hl-default">.</span><span class="hl-identifier">my_value</span><span class="hl-default"> = </span><span class="hl-quotes">&quot;</span><span class="hl-string">Don't set me!</span><span class="hl-quotes">&quot;
</span><span class="hl-reserved">print </span><span class="hl-identifier">my_instance</span><span class="hl-default">.</span><span class="hl-identifier">my_value</span></pre></div></div>
<p>When we run this, we get the following output:</p>
<div class="hl-surround" ><div class="hl-main"><pre><span class="hl-identifier">Getting a value
</span><span class="hl-number">23
</span><span class="hl-identifier">Don</span><span class="hl-quotes">'</span><span class="hl-string">t set me!</span></pre></div></div>
<p>As you can see we did not succeed in creating a read-only attribute, instead something else happened. The &#8220;Getting a value&#8221; string is printed out when we print out <code>my_value</code> for the first time. This means that we are accessing the value through the descriptor. We then set the value of the descriptor attribute and print out that new value. Since &#8220;Getting a value&#8221; isn&#8217;t printed out a second time, we know that the descriptor&#8217;s <code>__get__</code> method is not accessed when the second print statement is called.</p>
<p>Let&#8217;s take a closer look at what is happening using the following code, which prints out the instance&#8217;s <code>__dict__</code>:</p>
<div class="hl-surround" ><div class="hl-main"><pre><span class="hl-identifier">my_instance</span><span class="hl-default"> = </span><span class="hl-identifier">MyClass</span><span class="hl-brackets">(</span><span class="hl-number">23</span><span class="hl-brackets">) </span><span class="hl-comment">#Create the first instance
</span><span class="hl-reserved">print </span><span class="hl-identifier">my_instance</span><span class="hl-default">.</span><span class="hl-identifier">__dict__
my_instance</span><span class="hl-default">.</span><span class="hl-identifier">my_value</span><span class="hl-default"> = </span><span class="hl-quotes">&quot;</span><span class="hl-string">Don't set me!</span><span class="hl-quotes">&quot;
</span><span class="hl-reserved">print </span><span class="hl-identifier">my_instance</span><span class="hl-default">.</span><span class="hl-identifier">__dict__</span></pre></div></div>
<p>This results in the following, which explains what is happening:</p>
<div class="hl-surround" ><div class="hl-main"><pre><span class="hl-default">{</span><span class="hl-quotes">'</span><span class="hl-string">_value</span><span class="hl-quotes">'</span><span class="hl-default">: </span><span class="hl-number">23</span><span class="hl-default">}
{</span><span class="hl-quotes">'</span><span class="hl-string">_value</span><span class="hl-quotes">'</span><span class="hl-default">: </span><span class="hl-number">23</span><span class="hl-default">, </span><span class="hl-quotes">'</span><span class="hl-string">my_value</span><span class="hl-quotes">'</span><span class="hl-default">: </span><span class="hl-quotes">&quot;</span><span class="hl-string">Don't set me!</span><span class="hl-quotes">&quot;</span><span class="hl-default">}</span></pre></div></div>
<p>When we first access the <code>__dict__</code> we see our value indexed by the <code>_value</code> key that we told the descriptor to use. Now look at the second <code>__dict__</code>. The old value is still there, but so is a new value <code>my_value</code>. When we assigned &#8220;Don&#8217;t set me!&#8221; to <code>my_value</code>, we didn&#8217;t overwrite the descriptor attribute at class scope, we created a new instance attribute! And it is not exactly a read-only attribute.</p>
<p>In order to create a read-only attribute, you need to create a <code>data descriptor</code> where the <code>__set__</code> method raises an <code>AttributeError</code> exception. An easy way to do this is to create a <code>property</code> and only set the <code>fget</code> function. Instead of using the descriptor in Listing 4, we can construct a read-only attribute as follows:</p>
<div class="hl-surround" ><div class="hl-main"><pre><span class="hl-reserved">def </span><span class="hl-identifier">__get_value</span><span class="hl-brackets">(</span><span class="hl-identifier">self</span><span class="hl-brackets">)</span><span class="hl-default">:
    </span><span class="hl-reserved">return </span><span class="hl-identifier">self</span><span class="hl-default">.</span><span class="hl-identifier">_value
my_value</span><span class="hl-default"> = </span><span class="hl-builtin">property</span><span class="hl-brackets">(</span><span class="hl-identifier">__get_value</span><span class="hl-brackets">)</span></pre></div></div>
<h2>Conclusion</h2>
<p>I hope that after reading this article you can see how powerful descriptors (especially data-descriptors) can be. Once you get the hang of them, they are a great way to implement &#8220;getters and setters&#8221; and read-only attributes. Data-Descriptors are also very useful for performing validation during the assignment operation, i.e. ensuring that a value remains a specific type, or in a specific form.</p>
<p>The more you play with descriptors and use them in your code, the more you&#8217;ll see how sophisticated and useful they can be. That being said, it&#8217;s important to remember that unless you have a good reason to use descriptors you probably don&#8217;t need them. There&#8217;s no need to sacrifice the readability of your code or the dynamism of Python just for the sake of using descriptors. But when you have a real reason for managed attributes, you&#8217;ll find that descriptors are more than up to the task.</p>
<p>[1] <a href="http://docs.python.org/ref/descriptor-invocation.html">http://docs.python.org/ref/descriptor-invocation.html</a><br />
[2] <a href="http://www.python.org/download/releases/2.2/descrintro/#property">http://www.python.org/download/releases/2.2/descrintro/#property</a><br />
[3] <a href="http://docs.python.org/ref/descriptor-invocation.html">http://docs.python.org/ref/descriptor-invocation.html</a><br />
[4] <a href="http://docs.python.org/ref/descriptors.html">http://docs.python.org/ref/descriptors.html</a><br />
[5] <a href="http://docs.python.org/ref/descriptors.html">http://docs.python.org/ref/descriptors.html</a><br />
[6] <a href="http://docs.python.org/ref/descriptors.html">http://docs.python.org/ref/descriptors.html</a><br />
[7] <a href="http://www.python.org/download/releases/2.2/descrintro/#property">http://www.python.org/download/releases/2.2/descrintro/#property</a></p>
<div style="float:right;margin:0px 0px 0px 0px;"><a href="http://www.google.com/reader/link?url=http://www.learningpython.com/2010/04/25/introducing-descriptors-and-properties/&title=Introducing Descriptors and Properties&srcTitle=learning python&srcURL=http://www.learningpython.com"target="_blank" rel=""><img border="0" src="http://www.learningpython.com/wp-content/plugins/wp-google-buzz/icon/12.png" style="opacity:1;filter:alpha(opacity=100)" onmouseover="this.style.opacity=0.8;this.filters.alpha.opacity=70" onmouseout="this.style.opacity=1;this.filters.alpha.opacity=100"/> </a></div>]]></content:encoded>
			<wfw:commentRss>http://www.learningpython.com/2010/04/25/introducing-descriptors-and-properties/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>AVC: Simplifying your GUI Code</title>
		<link>http://www.learningpython.com/2010/03/14/avc-simplifying-your-gui-code/</link>
		<comments>http://www.learningpython.com/2010/03/14/avc-simplifying-your-gui-code/#comments</comments>
		<pubDate>Sun, 14 Mar 2010 14:44:46 +0000</pubDate>
		<dc:creator>selsine</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[avc]]></category>
		<category><![CDATA[gui]]></category>
		<category><![CDATA[PyGTK]]></category>
		<category><![CDATA[PyQt]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[Python Magazine]]></category>
		<category><![CDATA[wxWidget]]></category>

		<guid isPermaLink="false">http://www.learningpython.com/?p=169</guid>
		<description><![CDATA[
			
				
			
		
Note: This article was first published the April 2008 issue of Python Magazine
By: Mark Mruss
GUI programming, like many other types of programming, can sometimes prove exhausting because you must repeat yourself over and over again. AVC is one tool available to Python GUI programmers that attempts to simplify things by synchronizing application data and GUI [...]]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style="float: right; margin-left: 10px;">
			<a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fwww.learningpython.com%2F2010%2F03%2F14%2Favc-simplifying-your-gui-code%2F"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fwww.learningpython.com%2F2010%2F03%2F14%2Favc-simplifying-your-gui-code%2F&amp;style=normal" height="61" width="50" /><br />
			</a>
		</div>
<p>Note: This article was first published the <a href="http://www.pythonmagazine.com/c/issue/view/68">April 2008</a> issue of <a href="http://www.pythonmagazine.com/">Python Magazine</a></p>
<p><strong>By: Mark Mruss</strong></p>
<p>GUI programming, like many other types of programming, can sometimes prove exhausting because you must repeat yourself over and over again. <a href="http://avc.inrim.it/html/">AVC</a> is one tool available to Python GUI programmers that attempts to simplify things by synchronizing application data and GUI widgets.</p>
<h2>Introduction</h2>
<p>Every once in a while I find myself browsing the Internet trying to find out what&#8217;s new and exciting in the Python world. Sometimes I browse to find topics for this article; other times mere curiosity draws me across the web. While I was browsing the other day, I stumbled across <em>AVC: the Application View Controller</em> <a href="http://avc.inrim.it/html/">[1]</a>. I was immediately intrigued by it because its’ name is so similar to the Model View Controller (MVC) pattern. Being familiar with the Model View Controller pattern, and admittedly having  struggles with it in the past, I decided to check out AVC to determine if it might be a viable alternative.</p>
<p>After reading about AVC I was intrigued for several reasons. The main reason was the promise of &#8220;a multiplatform, fully automatic, live connection among graphical interface widgets and application variables.&#8221; <a href="http://avc.inrim.it/html/">[2]</a> This means that graphical widgets can be connected to variables and automatically synchronized. One of the (many?) problems with Graphical User Interface (GUI) programming is that you often find yourself doing the same thing over and over again. One of the things that you end of doing over and over again is setting the contents of a widget based on the value of a variable, and then subsequently, setting that variable&#8217;s value based on the current state of the widget. Whenever someone promises me an automatic connection between GUI widgets and my variables, I&#8217;m interested.</p>
<p><span id="more-169"></span></p>
<p>The other reason for investigating AVC is my past struggles with the Model View Controller pattern. I like the decoupling that the MVC pattern seems to provide, but I often feel as though I am needlessly duplicating code in order to stick with the pattern.  I looked into AVC hoping to find a simple framework that will avoid this and guide the separation of my application data from my GUI logic. However in the end, I realized that AVC (in its current state), does not appear to achieve this across all widget toolkits. It does allow you to separate your application from much of the GUI logic that one would normally need, but it does not appear to allow you to fully separate the data from the GUI.</p>
<p>AVC is being developed by Fabrizio Pollastri, and is released under version 3 of the GPL. I was unable to find much information about the project’s future or design objectives. But judging by the release notes, it is still being actively developed.  The project is only at version 0.5 so don’t be surprised if the API (Application Programming Interface) or some of the goals change.  Although relatively new, AVC bears further investigation because it already simplifies your GUI programming and contains the potential to do much more.  In this article, I will introduce some of the main concepts behind AVC, and provide a small, working example using AVC and PyGTK.</p>
<h2>Installing AVC</h2>
<p>AVC is a &#8220;Python module written in pure python&#8221; <a href="http://avc.inrim.it/html/">[3]</a>. This means that AVC is easy to install and does not have any dependencies aside from Python 2.2 or greater. You can download the current version (0.5.0) from the website or, if you are a lucky Linux user like me, you can install via your handy package manger.  If you download the source, you can install it after extraction, using the following command:</p>
<div class="hl-surround" style="height:28px;"><div class="hl-main"><pre><span class="hl-identifier">python setup</span><span class="hl-default">.</span><span class="hl-identifier">py install</span></pre></div></div>
<p>Depending on which widget toolkit you plan on using, the following requirements must also be met:</p>
<ul>
<li><strong>GTK+:</strong> PyGTK 2.8 &#8211; 2.10</li>
<li><strong>Qt:</strong> PyQt or PyQt4v3 &#8211; v4</li>
<li><strong>Tk:</strong> Tkinter 2.4</li>
<li><strong>wxWidgets:</strong> wxPython 2.6</li>
</ul>
<p>You can easily install any of the above toolkits using your favourite package manager, a source archive, or a binary installer found on each toolkit’s main website. Once AVC is installed, you can test the installation by importing the <code>avc</code> module from the interactive interpreter. If all goes well you will see something similar to the following:</p>
<div class="hl-surround" ><div class="hl-main"><pre><span class="hl-default">$ </span><span class="hl-identifier">python
Python </span><span class="hl-number">2.4.4 </span><span class="hl-brackets">(</span><span class="hl-comment">#2, Jan  3 2008, 13:36:28)
</span><span class="hl-brackets">[</span><span class="hl-identifier">GCC </span><span class="hl-number">4.2.3 20071123 </span><span class="hl-brackets">(</span><span class="hl-identifier">prerelease</span><span class="hl-brackets">) (</span><span class="hl-identifier">Debian </span><span class="hl-number">4.2.2</span><span class="hl-code">-</span><span class="hl-number">4</span><span class="hl-brackets">)] </span><span class="hl-identifier">on linux2
Type </span><span class="hl-quotes">&quot;</span><span class="hl-string">help</span><span class="hl-quotes">&quot;</span><span class="hl-code">, </span><span class="hl-quotes">&quot;</span><span class="hl-string">copyright</span><span class="hl-quotes">&quot;</span><span class="hl-code">, </span><span class="hl-quotes">&quot;</span><span class="hl-string">credits</span><span class="hl-quotes">&quot; </span><span class="hl-reserved">or </span><span class="hl-quotes">&quot;</span><span class="hl-string">license</span><span class="hl-quotes">&quot; </span><span class="hl-reserved">for </span><span class="hl-identifier">more information</span><span class="hl-code">.
&gt;&gt;&gt; </span><span class="hl-reserved">import </span><span class="hl-identifier">avc</span><span class="hl-code">
&gt;&gt;&gt;</span></pre></div></div>
<h2>Widget Support</h2>
<p>In its current state, AVC does not support all widgets available across all toolkits. It does currently support the following widgets:</p>
<ul>
<li>Button</li>
<li>Check Box</li>
<li>Combo Box (Not supported in Tk)</li>
<li>Entry</li>
<li>Label</li>
<li>Radio Button</li>
<li>Slider</li>
<li>Spin Button</li>
<li>Status Bar (Only supported by GTK+ and wxWidgets)</li>
<li>Text View</li>
<li>Toggle Button.</li>
</ul>
<p>The support of each of these widget types is then handled by specific widgets in each toolkit.</p>
<h2>Name-Matching</h2>
<p>In order to automatically synchronize variables and GUI widgets, AVC uses a name-matching technique. AVC supports two methods of name matching. The first method requires that the variable and the widget have the same name. For example, if you have a variable named <code>my_data</code> it will match with a widget also named <code>my_data</code>. In other words, if a variable and a widget have the same name they will be connected and their values synchronized.</p>
<p>The second name-matching technique allows you to connect variables to one or more widgets. Widgets can only be connected to one variable, but variables can be connected to any number of widgets. Using the second name-matching technique, you have a match if the widget name contains a double-underscore (<code>__</code>), <strong>and</strong> the portion before the double-underscore matches the variable name. For example, if you have variable named <code>my_numeric_value</code> and you want to match it with a Label widget and an Entry widget, you do this by naming the widgets as follows:</p>
<div class="hl-surround" ><div class="hl-main"><pre><span class="hl-identifier">my_numeric_value__label
my_numeric_value__entry</span></pre></div></div>
<p>Again, the text before the &#8220;__&#8221; must match the variable name, and the text after the &#8220;__&#8221; can be whatever you want to differentiate your widgets or ensure uniqueness (if the toolkit requires it).</p>
<h2>A GTK+, PyGTK, and AVC Example</h2>
<p>For this AVC example, I will use the GTK+ widget toolkit and PyGTK. PyGTK a &#8220;is a set of bindings to the GTK+ user interface toolkit for the Python language&#8221; <a href="http://faq.pygtk.org/index.py?req=all#1.1">[4]</a>. This means that it lets us write GUI applications in Python using the GTK+ widget toolkit. To avoid any flame wars: I did not choose GTK+ because it is the best toolkit but because it is the toolkit with which I am the most familiar.  In order to run this example you will need to have PyGTK 2.8 or later installed. You can get the latest version of PyGTK from the PyGTK website. <a href="http://www.pygtk.org/downloads.html">[5]</a></p>
<p>As I mentioned earlier, AVC works with many different widgets types. It also has many different features. I won&#8217;t be covering all of the features or widgets types in this column; if you are interesting in learning about some of these features or how to work with different widgets types, please see the AVC documentation. <a href="http://avc.inrim.it/doc/user_manual.pdf">[6]</a></p>
<p>This example is relatively simple, but it should illustrate some of the basic features of AVC. The example application asks for a person’s name and then displays that name in pop-up dialog. It will have the following features:</p>
<ol>
<li>A <code>gtk.TextView</code> widget to display the person&#8217;s name and allow the name to be edited. The <code>gtk.TextView</code> widget will be synchronised with a variable.</li>
<li>A <code>gtkButton</code> that will pop-up a <code>gtk.MessageDialog</code> to show the person&#8217;s name.</li>
<li>A <code>gtk.Button</code> that will reset the name to the name with which the application was initialized.</li>
</ol>
<p>To begin we need to import all of the modules necessary:</p>
<div class="hl-surround" ><div class="hl-main"><pre><span class="hl-reserved">import </span><span class="hl-identifier">gtk
</span><span class="hl-reserved">import </span><span class="hl-identifier">avc</span><span class="hl-default">.</span><span class="hl-identifier">avcgtk</span></pre></div></div>
<p><strong>Note</strong>: I am using a <code>gtk.TextView</code> widget instead of a <code>gtk.Entry</code> widget. In its current state, AVC does not propagate changes in <code>gtk.Entry</code> widgets back to the connected variable. I&#8217;m not sure if this is a current limitation or part of the design.</p>
<p>The above code imports the PyGTK module necessary to work with GTK+. It also imports the <code>avcgtk</code> module, which is used to link our &#8220;application variables&#8221; with our GTK+ GUI. Depending on what widget toolkit you use, you will have to use different modules. For example, if you are working with Qt4, you will import:</p>
<div class="hl-surround" style="height:28px;"><div class="hl-main"><pre><span class="hl-reserved">import </span><span class="hl-identifier">avc</span><span class="hl-default">.</span><span class="hl-identifier">avcqt4</span></pre></div></div>
<p>The next step is to create the &#8220;application&#8221; class. This will be the class that contains the data. In this example it will also create the GUI:</p>
<div class="hl-surround" style="height:28px;"><div class="hl-main"><pre><span class="hl-reserved">class </span><span class="hl-identifier">gtkAVC</span><span class="hl-brackets">(</span><span class="hl-identifier">avc</span><span class="hl-code">.</span><span class="hl-identifier">avcgtk</span><span class="hl-code">.</span><span class="hl-identifier">AVC</span><span class="hl-brackets">)</span><span class="hl-default">:</span></pre></div></div>
<p>Notice that we derive our application from the <code>avcgtk</code> module&#8217;s AVC class. This is the GTK+ specific AVC class with which we will work. We will also create an <code>__init__</code> method in the <code>gtkAVC</code> class. This is where we will initialize the data that will be connected to the GUI and create the GUI via the <code>init_gui</code> method:</p>
<div class="hl-surround" ><div class="hl-main"><pre><span class="hl-reserved">def </span><span class="hl-identifier">__init__</span><span class="hl-brackets">(</span><span class="hl-identifier">self</span><span class="hl-code">, </span><span class="hl-identifier">name</span><span class="hl-code">=</span><span class="hl-quotes">&quot;&quot;</span><span class="hl-brackets">)</span><span class="hl-default">:
    </span><span class="hl-comment">#set the variable and save the initial name
    </span><span class="hl-identifier">self</span><span class="hl-default">.</span><span class="hl-identifier">initial_name</span><span class="hl-default"> = </span><span class="hl-identifier">name
    self</span><span class="hl-default">.</span><span class="hl-identifier">name</span><span class="hl-default"> = </span><span class="hl-identifier">name
    </span><span class="hl-comment">#setup GUI
    </span><span class="hl-identifier">self</span><span class="hl-default">.</span><span class="hl-identifier">init_gui</span><span class="hl-brackets">()</span></pre></div></div>
<p>What we have here is pretty simple. We have the optional parameter <code>name</code> that we store as the current name and as the initial name. We then call the <code>init_gui</code> method that will create the GUI. The contents of the <code>init_gui</code> method can be seen in Listing 1. I won&#8217;t explain most of this code since the majority of it is PyGTK specific. However I will make note of several relevant segments below.</p>
<p><strong>Listing 1</strong></p>
<div class="hl-surround" style="height:280px;"><div class="hl-main"><pre><span class="hl-reserved">def </span><span class="hl-identifier">init_gui</span><span class="hl-brackets">(</span><span class="hl-identifier">self</span><span class="hl-brackets">)</span><span class="hl-default">:

    </span><span class="hl-comment">#Setup the window and the layout manager
    </span><span class="hl-identifier">self</span><span class="hl-default">.</span><span class="hl-identifier">window</span><span class="hl-default"> = </span><span class="hl-identifier">gtk</span><span class="hl-default">.</span><span class="hl-identifier">Window</span><span class="hl-brackets">()
    </span><span class="hl-identifier">self</span><span class="hl-default">.</span><span class="hl-identifier">window</span><span class="hl-default">.</span><span class="hl-identifier">connect</span><span class="hl-brackets">(</span><span class="hl-quotes">&quot;</span><span class="hl-string">destroy</span><span class="hl-quotes">&quot;</span><span class="hl-code">, </span><span class="hl-identifier">gtk</span><span class="hl-code">.</span><span class="hl-identifier">main_quit</span><span class="hl-brackets">)

    </span><span class="hl-identifier">self</span><span class="hl-default">.</span><span class="hl-identifier">h_layout</span><span class="hl-default"> = </span><span class="hl-identifier">gtk</span><span class="hl-default">.</span><span class="hl-identifier">HBox</span><span class="hl-brackets">()
    </span><span class="hl-identifier">self</span><span class="hl-default">.</span><span class="hl-identifier">window</span><span class="hl-default">.</span><span class="hl-identifier">add</span><span class="hl-brackets">(</span><span class="hl-identifier">self</span><span class="hl-code">.</span><span class="hl-identifier">h_layout</span><span class="hl-brackets">)

    </span><span class="hl-comment">#create the widgets
    </span><span class="hl-identifier">self</span><span class="hl-default">.</span><span class="hl-identifier">text_label</span><span class="hl-default"> = </span><span class="hl-identifier">gtk</span><span class="hl-default">.</span><span class="hl-identifier">Label</span><span class="hl-brackets">(</span><span class="hl-quotes">&quot;</span><span class="hl-string">Say hello:</span><span class="hl-quotes">&quot;</span><span class="hl-brackets">)
    </span><span class="hl-identifier">self</span><span class="hl-default">.</span><span class="hl-identifier">h_layout</span><span class="hl-default">.</span><span class="hl-identifier">add</span><span class="hl-brackets">(</span><span class="hl-identifier">self</span><span class="hl-code">.</span><span class="hl-identifier">text_label</span><span class="hl-brackets">)

    </span><span class="hl-identifier">self</span><span class="hl-default">.</span><span class="hl-identifier">frame</span><span class="hl-default"> = </span><span class="hl-identifier">gtk</span><span class="hl-default">.</span><span class="hl-identifier">Frame</span><span class="hl-brackets">()
    </span><span class="hl-identifier">self</span><span class="hl-default">.</span><span class="hl-identifier">h_layout</span><span class="hl-default">.</span><span class="hl-identifier">add</span><span class="hl-brackets">(</span><span class="hl-identifier">self</span><span class="hl-code">.</span><span class="hl-identifier">frame</span><span class="hl-brackets">)
    </span><span class="hl-identifier">self</span><span class="hl-default">.</span><span class="hl-identifier">scrolled_window</span><span class="hl-default"> = </span><span class="hl-identifier">gtk</span><span class="hl-default">.</span><span class="hl-identifier">ScrolledWindow</span><span class="hl-brackets">()
    </span><span class="hl-identifier">self</span><span class="hl-default">.</span><span class="hl-identifier">frame</span><span class="hl-default">.</span><span class="hl-identifier">add</span><span class="hl-brackets">(</span><span class="hl-identifier">self</span><span class="hl-code">.</span><span class="hl-identifier">scrolled_window</span><span class="hl-brackets">)

    </span><span class="hl-identifier">self</span><span class="hl-default">.</span><span class="hl-identifier">text_view</span><span class="hl-default"> = </span><span class="hl-identifier">gtk</span><span class="hl-default">.</span><span class="hl-identifier">TextView</span><span class="hl-brackets">()
    </span><span class="hl-identifier">self</span><span class="hl-default">.</span><span class="hl-identifier">text_view</span><span class="hl-default">.</span><span class="hl-identifier">set_name</span><span class="hl-brackets">(</span><span class="hl-quotes">&quot;</span><span class="hl-string">name__text_view</span><span class="hl-quotes">&quot;</span><span class="hl-brackets">)
    </span><span class="hl-identifier">self</span><span class="hl-default">.</span><span class="hl-identifier">scrolled_window</span><span class="hl-default">.</span><span class="hl-identifier">add</span><span class="hl-brackets">(</span><span class="hl-identifier">self</span><span class="hl-code">.</span><span class="hl-identifier">text_view</span><span class="hl-brackets">)

    </span><span class="hl-identifier">self</span><span class="hl-default">.</span><span class="hl-identifier">hello_button</span><span class="hl-default"> = </span><span class="hl-identifier">gtk</span><span class="hl-default">.</span><span class="hl-identifier">Button</span><span class="hl-brackets">(</span><span class="hl-quotes">&quot;</span><span class="hl-string">Hello!</span><span class="hl-quotes">&quot;</span><span class="hl-brackets">)
    </span><span class="hl-identifier">self</span><span class="hl-default">.</span><span class="hl-identifier">hello_button</span><span class="hl-default">.</span><span class="hl-identifier">connect</span><span class="hl-brackets">(</span><span class="hl-quotes">&quot;</span><span class="hl-string">clicked</span><span class="hl-quotes">&quot;</span><span class="hl-code">, </span><span class="hl-identifier">self</span><span class="hl-code">.</span><span class="hl-identifier">on_hello_clicked</span><span class="hl-brackets">)
    </span><span class="hl-identifier">self</span><span class="hl-default">.</span><span class="hl-identifier">h_layout</span><span class="hl-default">.</span><span class="hl-identifier">add</span><span class="hl-brackets">(</span><span class="hl-identifier">self</span><span class="hl-code">.</span><span class="hl-identifier">hello_button</span><span class="hl-brackets">)

    </span><span class="hl-identifier">self</span><span class="hl-default">.</span><span class="hl-identifier">reset_button</span><span class="hl-default"> = </span><span class="hl-identifier">gtk</span><span class="hl-default">.</span><span class="hl-identifier">Button</span><span class="hl-brackets">(</span><span class="hl-quotes">&quot;</span><span class="hl-string">Reset</span><span class="hl-quotes">&quot;</span><span class="hl-brackets">)
    </span><span class="hl-identifier">self</span><span class="hl-default">.</span><span class="hl-identifier">reset_button</span><span class="hl-default">.</span><span class="hl-identifier">connect</span><span class="hl-brackets">(</span><span class="hl-quotes">&quot;</span><span class="hl-string">clicked</span><span class="hl-quotes">&quot;</span><span class="hl-code">, </span><span class="hl-identifier">self</span><span class="hl-code">.</span><span class="hl-identifier">on_reset_clicked</span><span class="hl-brackets">)
    </span><span class="hl-identifier">self</span><span class="hl-default">.</span><span class="hl-identifier">h_layout</span><span class="hl-default">.</span><span class="hl-identifier">add</span><span class="hl-brackets">(</span><span class="hl-identifier">self</span><span class="hl-code">.</span><span class="hl-identifier">reset_button</span><span class="hl-brackets">)

    </span><span class="hl-identifier">self</span><span class="hl-default">.</span><span class="hl-identifier">window</span><span class="hl-default">.</span><span class="hl-identifier">show_all</span><span class="hl-brackets">()</span></pre></div></div>
<p>The only AVC specific code segment in the <code>init_gui</code> function is where we set the name of the <code>gtk.TextView</code> widget:</p>
<div class="hl-surround" style="height:28px;"><div class="hl-main"><pre><span class="hl-identifier">self</span><span class="hl-default">.</span><span class="hl-identifier">text_view</span><span class="hl-default">.</span><span class="hl-identifier">set_name</span><span class="hl-brackets">(</span><span class="hl-quotes">&quot;</span><span class="hl-string">name__text_view</span><span class="hl-quotes">&quot;</span><span class="hl-brackets">)</span></pre></div></div>
<p>This is all the code that we need to connect the <code>gtk.TextView</code> widget with the <code>name</code> variable that we created at the beginning of the <code>__init__</code> function. (Now, how&#8217;s that for simple?) Notice that the <code>name</code> section of the &#8220;name__text_view&#8221; string will match with the <code>self.name</code> variable. It is also important to note that the variable and the widget are not yet connected. They will become connected when the <code>avc_init</code> method is called.</p>
<p>The other non-AVC related code of note is the connection of both <code>gtk.Button</code> widgets’ clicked signals with signal handlers. We connect the &#8220;hello&#8221; button to the <code>on_hello_clicked</code> method and the &#8220;reset&#8221; button to the <code>on_reset_clicked</code> method.</p>
<p>That&#8217;s it for the <code>init_gui</code> function, now let&#8217;s look at the two signal handlers. The <code>on_hello_clicked</code> method, shown in Listing 2, simply displays the name in a <code>gtk.MessageDialog</code>. What should be interesting to GUI programmers about this function is that instead of reading the data from the <code>gtk.TextView</code> widget, we simply reference <code>self.name</code> for the dialog&#8217;s text. We can do this because <code>self.name</code> and the <code>gtk.TextView</code> widget are connected and their values are always the same.</p>
<p><strong>Listing 2</strong></p>
<div class="hl-surround" ><div class="hl-main"><pre><span class="hl-reserved">def </span><span class="hl-identifier">on_hello_clicked</span><span class="hl-brackets">(</span><span class="hl-identifier">self</span><span class="hl-code">, </span><span class="hl-identifier">widget</span><span class="hl-brackets">)</span><span class="hl-default">:
    </span><span class="hl-reserved">def </span><span class="hl-identifier">close</span><span class="hl-brackets">(</span><span class="hl-identifier">dialog</span><span class="hl-code">, </span><span class="hl-identifier">response</span><span class="hl-brackets">)</span><span class="hl-default">:
        </span><span class="hl-comment">#Close the dialog on ok
        </span><span class="hl-identifier">dialog</span><span class="hl-default">.</span><span class="hl-identifier">destroy</span><span class="hl-brackets">()
    </span><span class="hl-identifier">message_dlg</span><span class="hl-default"> = </span><span class="hl-identifier">gtk</span><span class="hl-default">.</span><span class="hl-identifier">MessageDialog</span><span class="hl-brackets">(</span><span class="hl-identifier">self</span><span class="hl-code">.</span><span class="hl-identifier">window</span><span class="hl-code">
        , </span><span class="hl-number">0</span><span class="hl-code">
        , </span><span class="hl-identifier">gtk</span><span class="hl-code">.</span><span class="hl-identifier">MESSAGE_INFO</span><span class="hl-code">
        , </span><span class="hl-identifier">gtk</span><span class="hl-code">.</span><span class="hl-identifier">BUTTONS_OK</span><span class="hl-code">
        , </span><span class="hl-brackets">(</span><span class="hl-quotes">&quot;</span><span class="hl-string">Hello: %s</span><span class="hl-quotes">&quot;</span><span class="hl-code"> % </span><span class="hl-identifier">self</span><span class="hl-code">.</span><span class="hl-identifier">name</span><span class="hl-brackets">))
    </span><span class="hl-identifier">message_dlg</span><span class="hl-default">.</span><span class="hl-identifier">connect</span><span class="hl-brackets">(</span><span class="hl-quotes">&quot;</span><span class="hl-string">response</span><span class="hl-quotes">&quot;</span><span class="hl-code">, </span><span class="hl-identifier">close</span><span class="hl-brackets">)
    </span><span class="hl-identifier">message_dlg</span><span class="hl-default">.</span><span class="hl-identifier">run</span><span class="hl-brackets">()</span></pre></div></div>
<p>The <code>on_reset_clicked</code> function is also very simple and straightforward. We simply reset the name to the initial name:</p>
<div class="hl-surround" ><div class="hl-main"><pre><span class="hl-reserved">def </span><span class="hl-identifier">on_reset_clicked</span><span class="hl-brackets">(</span><span class="hl-identifier">self</span><span class="hl-code">, </span><span class="hl-identifier">widget</span><span class="hl-brackets">)</span><span class="hl-default">:
    </span><span class="hl-comment">#Reset the name to the initial name
    </span><span class="hl-identifier">self</span><span class="hl-default">.</span><span class="hl-identifier">name</span><span class="hl-default"> = </span><span class="hl-identifier">self</span><span class="hl-default">.</span><span class="hl-identifier">initial_name</span></pre></div></div>
<p>Again, notice that we don&#8217;t have to worry about doing anything to the <code>gtk.TextView</code> widget that displays the current name. By simply modifying the data, what is displayed in the GUI will automatically be updated by AVC.</p>
<p>The next and final step in our test application is to create our class instances and actually show the GUI:</p>
<div class="hl-surround" ><div class="hl-main"><pre><span class="hl-identifier">if </span><span class="hl-brackets">(</span><span class="hl-identifier">__name__</span><span class="hl-code"> == </span><span class="hl-quotes">&quot;</span><span class="hl-string">__main__</span><span class="hl-quotes">&quot;</span><span class="hl-brackets">)</span><span class="hl-default">:
    </span><span class="hl-identifier">gtk_avc</span><span class="hl-default"> = </span><span class="hl-identifier">gtkAVC</span><span class="hl-brackets">(</span><span class="hl-quotes">&quot;</span><span class="hl-string">Mark Mruss</span><span class="hl-quotes">&quot;</span><span class="hl-brackets">)
    </span><span class="hl-identifier">gtk_avc</span><span class="hl-default">.</span><span class="hl-identifier">avc_init</span><span class="hl-brackets">()
    </span><span class="hl-identifier">gtk</span><span class="hl-default">.</span><span class="hl-identifier">main</span><span class="hl-brackets">()</span></pre></div></div>
<p>Since I am working in a Python file, I perform a simple test to make sure that the file is being launched directly instead of being imported as a module. I then create an instance of the <code>gtkAVC</code> class setting the name to be my name. The <code>avc_init</code> method is then called (which is a member of the <code>avc.avcgtk.AVC</code> class). The <code>avc_init</code> method is where all of the magic happens.  It is where AVC goes through an application&#8217;s variables and connects them to the GUI widgets based upon the name matching technique explained earlier. <code>avc_init</code> must be called <strong>after</strong> all of the data in the &#8220;application&#8221; and the widgets have been created.</p>
<p>The final step in this example, is to run the <code>gtk.main</code> function. This is the &#8220;main loop&#8221; of our PyGTK based application and is standard when working with PyGTK.</p>
<p>The entire code can be seen in Listing 3. When you run the code you will be greeted with something similar to Figure 1. It may not seem like much, but what we have here is a fully functional AVC &#8220;application&#8221;. This simple &#8220;application&#8221; illustrates how easy it is to create an automatic connection between your data and your GUI.</p>
<div id="attachment_172" class="wp-caption alignnone" style="width: 310px"><img src="http://www.learningpython.com/wp-content/uploads/2010/03/Figure1-300x230.png" alt="Figure1" title="Figure1" width="300" height="230" class="size-medium wp-image-172" /><p class="wp-caption-text">Figure1</p></div>
<p><strong>Listing 3</strong></p>
<div class="hl-surround" style="height:280px;"><div class="hl-main"><pre><span class="hl-comment">#! /usr/bin/env python
</span><span class="hl-reserved">import </span><span class="hl-identifier">gtk
</span><span class="hl-reserved">import </span><span class="hl-identifier">avc</span><span class="hl-default">.</span><span class="hl-identifier">avcgtk

</span><span class="hl-reserved">class </span><span class="hl-identifier">gtkAVC</span><span class="hl-brackets">(</span><span class="hl-identifier">avc</span><span class="hl-code">.</span><span class="hl-identifier">avcgtk</span><span class="hl-code">.</span><span class="hl-identifier">AVC</span><span class="hl-brackets">)</span><span class="hl-default">:

    </span><span class="hl-reserved">def </span><span class="hl-identifier">__init__</span><span class="hl-brackets">(</span><span class="hl-identifier">self</span><span class="hl-code">, </span><span class="hl-identifier">name</span><span class="hl-code">=</span><span class="hl-quotes">&quot;&quot;</span><span class="hl-brackets">)</span><span class="hl-default">:
        </span><span class="hl-comment">#set the variable and save the initial name
        </span><span class="hl-identifier">self</span><span class="hl-default">.</span><span class="hl-identifier">initial_name</span><span class="hl-default"> = </span><span class="hl-identifier">name
        self</span><span class="hl-default">.</span><span class="hl-identifier">name</span><span class="hl-default"> = </span><span class="hl-identifier">name
        </span><span class="hl-comment">#setup GUI
        </span><span class="hl-identifier">self</span><span class="hl-default">.</span><span class="hl-identifier">init_gui</span><span class="hl-brackets">()

    </span><span class="hl-reserved">def </span><span class="hl-identifier">init_gui</span><span class="hl-brackets">(</span><span class="hl-identifier">self</span><span class="hl-brackets">)</span><span class="hl-default">:

        </span><span class="hl-comment">#Setup the window and the layout manager
        </span><span class="hl-identifier">self</span><span class="hl-default">.</span><span class="hl-identifier">window</span><span class="hl-default"> = </span><span class="hl-identifier">gtk</span><span class="hl-default">.</span><span class="hl-identifier">Window</span><span class="hl-brackets">()
        </span><span class="hl-identifier">self</span><span class="hl-default">.</span><span class="hl-identifier">window</span><span class="hl-default">.</span><span class="hl-identifier">connect</span><span class="hl-brackets">(</span><span class="hl-quotes">&quot;</span><span class="hl-string">destroy</span><span class="hl-quotes">&quot;</span><span class="hl-code">, </span><span class="hl-identifier">gtk</span><span class="hl-code">.</span><span class="hl-identifier">main_quit</span><span class="hl-brackets">)

        </span><span class="hl-identifier">self</span><span class="hl-default">.</span><span class="hl-identifier">h_layout</span><span class="hl-default"> = </span><span class="hl-identifier">gtk</span><span class="hl-default">.</span><span class="hl-identifier">HBox</span><span class="hl-brackets">()
        </span><span class="hl-identifier">self</span><span class="hl-default">.</span><span class="hl-identifier">window</span><span class="hl-default">.</span><span class="hl-identifier">add</span><span class="hl-brackets">(</span><span class="hl-identifier">self</span><span class="hl-code">.</span><span class="hl-identifier">h_layout</span><span class="hl-brackets">)

        </span><span class="hl-comment">#create the widgets
        </span><span class="hl-identifier">self</span><span class="hl-default">.</span><span class="hl-identifier">text_label</span><span class="hl-default"> = </span><span class="hl-identifier">gtk</span><span class="hl-default">.</span><span class="hl-identifier">Label</span><span class="hl-brackets">(</span><span class="hl-quotes">&quot;</span><span class="hl-string">Say hello:</span><span class="hl-quotes">&quot;</span><span class="hl-brackets">)
        </span><span class="hl-identifier">self</span><span class="hl-default">.</span><span class="hl-identifier">h_layout</span><span class="hl-default">.</span><span class="hl-identifier">add</span><span class="hl-brackets">(</span><span class="hl-identifier">self</span><span class="hl-code">.</span><span class="hl-identifier">text_label</span><span class="hl-brackets">)

        </span><span class="hl-identifier">self</span><span class="hl-default">.</span><span class="hl-identifier">frame</span><span class="hl-default"> = </span><span class="hl-identifier">gtk</span><span class="hl-default">.</span><span class="hl-identifier">Frame</span><span class="hl-brackets">()
        </span><span class="hl-identifier">self</span><span class="hl-default">.</span><span class="hl-identifier">h_layout</span><span class="hl-default">.</span><span class="hl-identifier">add</span><span class="hl-brackets">(</span><span class="hl-identifier">self</span><span class="hl-code">.</span><span class="hl-identifier">frame</span><span class="hl-brackets">)
        </span><span class="hl-identifier">self</span><span class="hl-default">.</span><span class="hl-identifier">scrolled_window</span><span class="hl-default"> = </span><span class="hl-identifier">gtk</span><span class="hl-default">.</span><span class="hl-identifier">ScrolledWindow</span><span class="hl-brackets">()
        </span><span class="hl-identifier">self</span><span class="hl-default">.</span><span class="hl-identifier">frame</span><span class="hl-default">.</span><span class="hl-identifier">add</span><span class="hl-brackets">(</span><span class="hl-identifier">self</span><span class="hl-code">.</span><span class="hl-identifier">scrolled_window</span><span class="hl-brackets">)

        </span><span class="hl-identifier">self</span><span class="hl-default">.</span><span class="hl-identifier">text_view</span><span class="hl-default"> = </span><span class="hl-identifier">gtk</span><span class="hl-default">.</span><span class="hl-identifier">TextView</span><span class="hl-brackets">()
        </span><span class="hl-identifier">self</span><span class="hl-default">.</span><span class="hl-identifier">text_view</span><span class="hl-default">.</span><span class="hl-identifier">set_name</span><span class="hl-brackets">(</span><span class="hl-quotes">&quot;</span><span class="hl-string">name__text_view</span><span class="hl-quotes">&quot;</span><span class="hl-brackets">)
        </span><span class="hl-identifier">self</span><span class="hl-default">.</span><span class="hl-identifier">scrolled_window</span><span class="hl-default">.</span><span class="hl-identifier">add</span><span class="hl-brackets">(</span><span class="hl-identifier">self</span><span class="hl-code">.</span><span class="hl-identifier">text_view</span><span class="hl-brackets">)

        </span><span class="hl-identifier">self</span><span class="hl-default">.</span><span class="hl-identifier">hello_button</span><span class="hl-default"> = </span><span class="hl-identifier">gtk</span><span class="hl-default">.</span><span class="hl-identifier">Button</span><span class="hl-brackets">(</span><span class="hl-quotes">&quot;</span><span class="hl-string">Hello!</span><span class="hl-quotes">&quot;</span><span class="hl-brackets">)
        </span><span class="hl-identifier">self</span><span class="hl-default">.</span><span class="hl-identifier">hello_button</span><span class="hl-default">.</span><span class="hl-identifier">connect</span><span class="hl-brackets">(</span><span class="hl-quotes">&quot;</span><span class="hl-string">clicked</span><span class="hl-quotes">&quot;</span><span class="hl-code">, </span><span class="hl-identifier">self</span><span class="hl-code">.</span><span class="hl-identifier">on_hello_clicked</span><span class="hl-brackets">)
        </span><span class="hl-identifier">self</span><span class="hl-default">.</span><span class="hl-identifier">h_layout</span><span class="hl-default">.</span><span class="hl-identifier">add</span><span class="hl-brackets">(</span><span class="hl-identifier">self</span><span class="hl-code">.</span><span class="hl-identifier">hello_button</span><span class="hl-brackets">)

        </span><span class="hl-identifier">self</span><span class="hl-default">.</span><span class="hl-identifier">reset_button</span><span class="hl-default"> = </span><span class="hl-identifier">gtk</span><span class="hl-default">.</span><span class="hl-identifier">Button</span><span class="hl-brackets">(</span><span class="hl-quotes">&quot;</span><span class="hl-string">Reset</span><span class="hl-quotes">&quot;</span><span class="hl-brackets">)
        </span><span class="hl-identifier">self</span><span class="hl-default">.</span><span class="hl-identifier">reset_button</span><span class="hl-default">.</span><span class="hl-identifier">connect</span><span class="hl-brackets">(</span><span class="hl-quotes">&quot;</span><span class="hl-string">clicked</span><span class="hl-quotes">&quot;</span><span class="hl-code">, </span><span class="hl-identifier">self</span><span class="hl-code">.</span><span class="hl-identifier">on_reset_clicked</span><span class="hl-brackets">)
        </span><span class="hl-identifier">self</span><span class="hl-default">.</span><span class="hl-identifier">h_layout</span><span class="hl-default">.</span><span class="hl-identifier">add</span><span class="hl-brackets">(</span><span class="hl-identifier">self</span><span class="hl-code">.</span><span class="hl-identifier">reset_button</span><span class="hl-brackets">)

        </span><span class="hl-identifier">self</span><span class="hl-default">.</span><span class="hl-identifier">window</span><span class="hl-default">.</span><span class="hl-identifier">show_all</span><span class="hl-brackets">()

    </span><span class="hl-reserved">def </span><span class="hl-identifier">on_hello_clicked</span><span class="hl-brackets">(</span><span class="hl-identifier">self</span><span class="hl-code">, </span><span class="hl-identifier">widget</span><span class="hl-brackets">)</span><span class="hl-default">:
        </span><span class="hl-reserved">def </span><span class="hl-identifier">close</span><span class="hl-brackets">(</span><span class="hl-identifier">dialog</span><span class="hl-code">, </span><span class="hl-identifier">response</span><span class="hl-brackets">)</span><span class="hl-default">:
            </span><span class="hl-comment">#Close the dialog on ok
            </span><span class="hl-identifier">dialog</span><span class="hl-default">.</span><span class="hl-identifier">destroy</span><span class="hl-brackets">()
        </span><span class="hl-identifier">message_dlg</span><span class="hl-default"> = </span><span class="hl-identifier">gtk</span><span class="hl-default">.</span><span class="hl-identifier">MessageDialog</span><span class="hl-brackets">(</span><span class="hl-identifier">self</span><span class="hl-code">.</span><span class="hl-identifier">window</span><span class="hl-code">
            , </span><span class="hl-number">0</span><span class="hl-code">
            , </span><span class="hl-identifier">gtk</span><span class="hl-code">.</span><span class="hl-identifier">MESSAGE_INFO</span><span class="hl-code">
            , </span><span class="hl-identifier">gtk</span><span class="hl-code">.</span><span class="hl-identifier">BUTTONS_OK</span><span class="hl-code">
            , </span><span class="hl-brackets">(</span><span class="hl-quotes">&quot;</span><span class="hl-string">Hello: %s</span><span class="hl-quotes">&quot;</span><span class="hl-code"> % </span><span class="hl-identifier">self</span><span class="hl-code">.</span><span class="hl-identifier">name</span><span class="hl-brackets">))
        </span><span class="hl-identifier">message_dlg</span><span class="hl-default">.</span><span class="hl-identifier">connect</span><span class="hl-brackets">(</span><span class="hl-quotes">&quot;</span><span class="hl-string">response</span><span class="hl-quotes">&quot;</span><span class="hl-code">, </span><span class="hl-identifier">close</span><span class="hl-brackets">)
        </span><span class="hl-identifier">message_dlg</span><span class="hl-default">.</span><span class="hl-identifier">run</span><span class="hl-brackets">()

    </span><span class="hl-reserved">def </span><span class="hl-identifier">on_reset_clicked</span><span class="hl-brackets">(</span><span class="hl-identifier">self</span><span class="hl-code">, </span><span class="hl-identifier">widget</span><span class="hl-brackets">)</span><span class="hl-default">:
        </span><span class="hl-comment">#Reset the name to the initial name
        </span><span class="hl-identifier">self</span><span class="hl-default">.</span><span class="hl-identifier">name</span><span class="hl-default"> = </span><span class="hl-identifier">self</span><span class="hl-default">.</span><span class="hl-identifier">initial_name

if </span><span class="hl-brackets">(</span><span class="hl-identifier">__name__</span><span class="hl-code"> == </span><span class="hl-quotes">&quot;</span><span class="hl-string">__main__</span><span class="hl-quotes">&quot;</span><span class="hl-brackets">)</span><span class="hl-default">:
    </span><span class="hl-identifier">gtk_avc</span><span class="hl-default"> = </span><span class="hl-identifier">gtkAVC</span><span class="hl-brackets">(</span><span class="hl-quotes">&quot;</span><span class="hl-string">Mark Mruss</span><span class="hl-quotes">&quot;</span><span class="hl-brackets">)
    </span><span class="hl-identifier">gtk_avc</span><span class="hl-default">.</span><span class="hl-identifier">avc_init</span><span class="hl-brackets">()
    </span><span class="hl-identifier">gtk</span><span class="hl-default">.</span><span class="hl-identifier">main</span><span class="hl-brackets">()</span></pre></div></div>
<h2>Benefits and Limitations</h2>
<p>For a project that is little more than one year old (the first release was in January 2007) AVC appears quite stable and ready to be used. This is not to say that AVC is perfect. I did encounter a few issues.</p>
<p>The most notable issue that I encountered is the tightly coupled structure that AVC seems to impose on your application. For a module that tries to simplify the relationship between application data and GUI&#8217;s, this feels like a bit of an issue because. For example, when testing using PyGTK I was able to easily separate the GUI and the &#8220;application&#8221; into separate classes. But when I tried to do the same thing using PyQt4, I encountered an error because the <code>avc_timer</code> function in the <code>avc.avcqt4.AVC</code> module expects that the &#8220;application&#8221; class is itself a <code>QObject</code> (namely the actual <code>QApplication</code>). I find this counterintuitive since being able to separate the data from the GUI-logic seems to be a goal of AVC and similar tools. If you are able to separate the &#8220;application&#8221; fully from the GUI, you can easily connect your &#8220;application&#8221; to different GUI&#8217;s, and (by changing the AVC base class) even different widget toolkits.</p>
<p>I would also be interested in the ability to connect more types of data to more types of widgets. For example, I am interested in synchronizing Python lists with the contents of List boxes and Combo boxes. This is in addition to the current ability to synchronize the selection in the two widgets with integers.</p>
<p>Of course AVC also has a lot going for it. For one, I really like that AVC works with different widget toolkits. I have not seen this very often. It is a real benefit, especially when it comes to people adopting AVC. Hopefully in the future AVC will allow for further separation of the data and the GUI, truly enabling us to use different GUI&#8217;s and different widget toolkits with our data.</p>
<p>What I like most about AVC is its simplicity. I have played around with similar solutions and AVC is one of the leaders in terms of ease of use. I was able to get create a simple AVC based application in almost no time at all. (The time that it did take was spent trying to remember PyGTK.) Much of this has to do with the streamlined nature of AVC. There is very little to configure regardless of what widget toolkit you use. While this simplicity limits what AVC can currently achieve compared to other solutions, it also makes the barrier to entry low and the usage trivial. User friendliness is certainly a good thing in a package that aims to make GUI application development easier.</p>
<h2>Conclusion</h2>
<p>While the data that we worked with in the earlier example wasn&#8217;t that complicated (a simple string), I hope that it illustrates how helpful AVC is if you are working with a large amount of data or data that could be updated by an external source. Instead of having to worry about what widgets or toolkits the data was being displayed in, AVC lets us work with the data and GUI transparently, leaving the synchronization to AVC.</p>
<p>If what AVC offers sounds interesting to you, download it from the AVC website and try it out.  Although it it&#8217;s not there just yet with enough attention, usage, and contributions from the Python community, AVC should reach full-feature status in no time.</p>
<p><a href="http://avc.inrim.it/html/">[1] http://avc.inrim.it/html/</a><br />
<a href="http://avc.inrim.it/html/">[2] http://avc.inrim.it/html/</a><br />
<a href="http://avc.inrim.it/html/">[3] http://avc.inrim.it/html/</a><br />
<a href="http://faq.pygtk.org/index.py?req=all#1.1">[4] http://faq.pygtk.org/index.py?req=all#1.1</a><br />
<a href="http://www.pygtk.org/downloads.html">[5] http://www.pygtk.org/downloads.html</a><br />
<a href="http://avc.inrim.it/doc/user_manual.pdf">[6] http://avc.inrim.it/doc/user_manual.pdf</a></p>
<p><strong>Note:</strong> If you haven&#8217;t already, please check out my <a href="http://www.learningpython.com/2010/03/04/poll-python-version/">Python version poll</a>.</p>
<div style="float:right;margin:0px 0px 0px 0px;"><a href="http://www.google.com/reader/link?url=http://www.learningpython.com/2010/03/14/avc-simplifying-your-gui-code/&title=AVC: Simplifying your GUI Code&srcTitle=learning python&srcURL=http://www.learningpython.com"target="_blank" rel=""><img border="0" src="http://www.learningpython.com/wp-content/plugins/wp-google-buzz/icon/12.png" style="opacity:1;filter:alpha(opacity=100)" onmouseover="this.style.opacity=0.8;this.filters.alpha.opacity=70" onmouseout="this.style.opacity=1;this.filters.alpha.opacity=100"/> </a></div>]]></content:encoded>
			<wfw:commentRss>http://www.learningpython.com/2010/03/14/avc-simplifying-your-gui-code/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Elegant XML parsing using the ElementTree Module</title>
		<link>http://www.learningpython.com/2008/05/07/elegant-xml-parsing-using-the-elementtree-module/</link>
		<comments>http://www.learningpython.com/2008/05/07/elegant-xml-parsing-using-the-elementtree-module/#comments</comments>
		<pubDate>Wed, 07 May 2008 16:21:48 +0000</pubDate>
		<dc:creator>selsine</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[tutorial]]></category>
		<category><![CDATA[xml]]></category>
		<category><![CDATA[ElementTree]]></category>

		<guid isPermaLink="false">http://www.learningpython.com/?p=74</guid>
		<description><![CDATA[
			
				
			
		
Mark Mruss
Note: This article was first published the October 2007 issue of Python Magazine
XML is everywhere.  It seems you can&#8217;t do much these days unless you utilize XML in one way or another. Fortunately, Python developers have a new tool in our standard arsenal: the ElementTree module. This article aims to introduce you to [...]]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style="float: right; margin-left: 10px;">
			<a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fwww.learningpython.com%2F2008%2F05%2F07%2Felegant-xml-parsing-using-the-elementtree-module%2F"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fwww.learningpython.com%2F2008%2F05%2F07%2Felegant-xml-parsing-using-the-elementtree-module%2F&amp;style=normal" height="61" width="50" /><br />
			</a>
		</div>
<p><strong>Mark Mruss</strong></p>
<p><strong>Note:</strong> This article was first published the October 2007 issue of <a href="http://www.pythonmagazine.com">Python Magazine</a></p>
<p>XML is everywhere.  It seems you can&#8217;t do much these days unless you utilize XML in one way or another. Fortunately, Python developers have a new tool in our standard arsenal: the ElementTree module. This article aims to introduce you to reading, writing, saving, and loading XML using the ElementTree module.</p>
<ol>
<li><a href="#Introduction">Introduction</a></li>
<li><a href="#ReadingXMLdata">Reading XML data</a></li>
<li><a href="#Listing1">Listing 1</a></li>
<li><a href="#Listing2">Listing 2</a></li>
<li><a href="#ReadingXMLAttributes">Reading XML Attributes</a></li>
<li><a href="#WritingXML">Writing XML</a></li>
<li><a href="#Listing3">Listing 3</a></li>
<li><a href="#WritingXMLAttributes">Writing XML Attributes</a></li>
<li><a href="#ReadingXMLFiles">Reading XML Files</a></li>
<li><a href="#WritingXMLDatatoaFile">Writing XML Data to a File</a></li>
<li><a href="#ReadingfromtheWeb">Reading from the Web</a></li>
<li><a href="#Conclusion">Conclusion</a></li>
</ol>
<p><span id="more-74"></span><!--more--></p>
<h2><a href="#Introduction">Introduction</a></h2>
<p>It seems like everyone needs to parse XML these days.  They&#8217;re either saving their own information in XML or loading in someone else&#8217;s data.  This is why I was glad to learn that as of Python 2.5, the <em>ElementTree</em> XML package has been added to the standard library in the XML module.</p>
<p>What I like about the <em>ElementTree</em> module is that it just seems to make sense.  This might seem like a strange thing to say about an XML module, but I&#8217;ve had to parse enough XML in my time to know that if an XML module makes sense the first time you use it, it&#8217;s probably a keeper. The <em>ElementTree</em> module allows me to work with XML data in a way that is similar to how I <em>think</em> about XML data.</p>
<p>A subset of the full <em>ElementTree</em> module is available in the Python 2.5 standard library as <code>xml.etree</code>, but you don&#8217;t have to use Python 2.5 in order to use the <em>ElementTree</em> module. If you are still using an older version of Python (1.5.2 or later) you can simply download the module from its website and manually install it on your system.  The website also has very easy to follow installation instructions, which you should consult to avoid issues while installing <em>ElementTree</em>.</p>
<p>In general, the <em>ElementTree</em> module treats XML data as a list of lists.  All XML has a root element that will have zero or more subelements (or child elements). Each of those subelements may in turn have subelements of their own.  The best way to think about this is with a brief example.</p>
<p>First let&#8217;s take a look at some sample XML data:</p>
<div class="hl-surround" ><div class="hl-main"><pre><span class="hl-default">&lt;</span><span class="hl-identifier">root</span><span class="hl-default">&gt;
&lt;</span><span class="hl-identifier">child</span><span class="hl-default">&gt;</span><span class="hl-identifier">One</span><span class="hl-default">&lt;/</span><span class="hl-identifier">child</span><span class="hl-default">&gt;
&lt;</span><span class="hl-identifier">child</span><span class="hl-default">&gt;</span><span class="hl-identifier">Two</span><span class="hl-default">&lt;/</span><span class="hl-identifier">child</span><span class="hl-default">&gt;
&lt;/</span><span class="hl-identifier">root</span><span class="hl-default">&gt;</span></pre></div></div>
<p>Here we have a root element with two child elements. Each child element has some text associated with it seen here as &#8220;one&#8221; and &#8220;two&#8221;. If we examine the XML as a hierarchical list of lists we see that we have one element &#8220;root&#8221; in our root list.  Within the &#8220;root&#8221; element we have a list containing two subelements &#8220;child&#8221; and &#8220;child&#8221;. The two &#8220;child&#8221; elements would then contain empty lists representing their lack of subelements. Not too complicated so far, is it?</p>
<h2><a href="#ReadingXMLdata">Reading XML data</a></h2>
<p>Now let&#8217;s use the <em>ElementTree</em> package to parse this XML and print the text data associated with each child element.  To start, we&#8217;ll create a Python file with the contents shown in Listing 1.</p>
<p><strong><a href="#Listing1">Listing 1</a></strong></p>
<div class="hl-surround" ><div class="hl-main"><pre><span class="hl-comment">#!/usr/bin/env python

</span><span class="hl-reserved">def </span><span class="hl-identifier">main</span><span class="hl-brackets">()</span><span class="hl-default">:
	</span><span class="hl-reserved">pass

if </span><span class="hl-identifier">__name__</span><span class="hl-default"> == </span><span class="hl-quotes">&quot;</span><span class="hl-string">__main__</span><span class="hl-quotes">&quot;</span><span class="hl-default">:
	</span><span class="hl-identifier">main</span><span class="hl-brackets">()</span></pre></div></div>
<p>This is basically a template that I use for many of my simple &#8220;*.py&#8221; files.  It doesn&#8217;t actually do anything except set up the script so that when the file is run, the <code>main</code> method will be executed. Some people like to use the Python interactive interpreter for simple hacking like this. Personally, I prefer having my code stored in a handy file so I can make simple changes and re-run the entire script when I am just playing around.</p>
<p>The first thing that we need to do in our Python code is import the <em>ElementTree</em> module:</p>
<div class="hl-surround" style="height:28px;"><div class="hl-main"><pre><span class="hl-reserved">from </span><span class="hl-identifier">xml</span><span class="hl-default">.</span><span class="hl-identifier">etree </span><span class="hl-reserved">import </span><span class="hl-identifier">ElementTree as ET</span></pre></div></div>
<p><strong>Note</strong>: If you are not using Python 2.5 and have installed the <em>ElementTree</em> module on your own, you should import the <em>ElementTree</em> module as follows:</p>
<div class="hl-surround" style="height:28px;"><div class="hl-main"><pre><span class="hl-reserved">from </span><span class="hl-identifier">elementtree </span><span class="hl-reserved">import </span><span class="hl-identifier">ElementTree as ET</span></pre></div></div>
<p>This will import the ElementTree section of the module into your program aliased as ET.  However, you don&#8217;t have to import <em>ElementTree</em> using an alias; you can simply import it and access it as <code>ElementTree</code>. Using ET is demonstrated in the Python 2.5 &#8220;What&#8217;s new&#8221; documentation[1] and I think it&#8217;s a great way to eliminate some key strokes.</p>
<p>Now we&#8217;ll begin writing code in the <code>main</code> method.  The first step is to load the XML data described above.  Normally you will be working with a file or URL; for now we want to keep this simple and load the XML data directly from the text:</p>
<div class="hl-surround" ><div class="hl-main"><pre><span class="hl-identifier">element</span><span class="hl-default"> = </span><span class="hl-identifier">ET</span><span class="hl-default">.</span><span class="hl-identifier">XML</span><span class="hl-brackets">(
       </span><span class="hl-quotes">&quot;</span><span class="hl-string">&lt;root&gt;&lt;child&gt;One&lt;/child&gt;&lt;child&gt;Two&lt;/child&gt;&lt;/root&gt;</span><span class="hl-quotes">&quot;</span><span class="hl-brackets">)</span></pre></div></div>
<p>The <code>XML</code> function is described in the <em>ElementTree</em> documentation as follows: &#8220;Parses an XML document from a string constant. This function can be used to embed &#8220;XML literals&#8221; in Python code&#8221;[2].</p>
<p>Be careful here! The <code>XML</code> function returns an Element object, and not an ElementTree object as one might expect. Element objects are used to represent XML elements, whereas the ElementTree object is used to represent the entire XML document. Element objects <em>may</em> represent the entire XML document if they are the root element but will not if they are a subelement. ElementTree objects also add &#8220;some extra support for serialization to and from standard XML.&#8221;[3] The Element object that is returned represents the <code><root></root></code> element in our XML data.</p>
<p>Thankfully, the Element object is an iterator object so we can use a <code>for</code> loop to loop through all of its child elements:</p>
<div class="hl-surround" style="height:28px;"><div class="hl-main"><pre><span class="hl-reserved">for </span><span class="hl-identifier">subelement </span><span class="hl-reserved">in </span><span class="hl-identifier">element</span><span class="hl-default">:</span></pre></div></div>
<p>This will give us all the child elements in the root element.  As mentioned earlier, each element in the XML tree is represented as an Element object, so as we iterate through the root element&#8217;s child elements we are getting Element objects with which to work. Meaning that each loop though the for loop will give us the next child element in the form of an Element object until there are no more children left. In order to print out the text associated with an Element object we simply have to access the Element object&#8217;s <code>text</code> attribute:</p>
<div class="hl-surround" ><div class="hl-main"><pre><span class="hl-reserved">for </span><span class="hl-identifier">subelement </span><span class="hl-reserved">in </span><span class="hl-identifier">element</span><span class="hl-default">:
       </span><span class="hl-reserved">print </span><span class="hl-identifier">subelement</span><span class="hl-default">.</span><span class="hl-identifier">text</span></pre></div></div>
<p>To recap, have a look at the code in Listing 2.</p>
<p><strong><a href="#Listing2">Listing 2</a></strong></p>
<div class="hl-surround" ><div class="hl-main"><pre><span class="hl-comment">#!/usr/bin/env python

</span><span class="hl-reserved">from </span><span class="hl-identifier">xml</span><span class="hl-default">.</span><span class="hl-identifier">etree </span><span class="hl-reserved">import </span><span class="hl-identifier">ElementTree as ET

</span><span class="hl-reserved">def </span><span class="hl-identifier">main</span><span class="hl-brackets">()</span><span class="hl-default">:
	</span><span class="hl-identifier">element</span><span class="hl-default"> = </span><span class="hl-identifier">ET</span><span class="hl-default">.</span><span class="hl-identifier">XML</span><span class="hl-brackets">(</span><span class="hl-quotes">&quot;</span><span class="hl-string">&lt;root&gt;&lt;child&gt;One&lt;/child&gt;&lt;child&gt;Two&lt;/child&gt;&lt;/root&gt;</span><span class="hl-quotes">&quot;</span><span class="hl-brackets">)
	</span><span class="hl-reserved">for </span><span class="hl-identifier">subelement </span><span class="hl-reserved">in </span><span class="hl-identifier">element</span><span class="hl-default">:
		</span><span class="hl-reserved">print </span><span class="hl-identifier">subelement</span><span class="hl-default">.</span><span class="hl-identifier">text

</span><span class="hl-reserved">if </span><span class="hl-identifier">__name__</span><span class="hl-default"> == </span><span class="hl-quotes">&quot;</span><span class="hl-string">__main__</span><span class="hl-quotes">&quot;</span><span class="hl-default">:
	</span><span class="hl-comment"># Someone is launching this directly
	</span><span class="hl-identifier">main</span><span class="hl-brackets">()</span></pre></div></div>
<p>Once you run the code you should get the following output:</p>
<div class="hl-surround" ><div class="hl-main"><pre><span class="hl-identifier">One
Two</span></pre></div></div>
<p>If an XML element does not have any text associated with it, like our root element, the Element object&#8217;s <code>text</code> attribute will be set to <code>None</code>. If you want to check if an element had any text associated with it, you can do the following:</p>
<div class="hl-surround" ><div class="hl-main"><pre><span class="hl-reserved">if </span><span class="hl-identifier">element</span><span class="hl-default">.</span><span class="hl-identifier">text </span><span class="hl-reserved">is not None</span><span class="hl-default">:
       </span><span class="hl-reserved">print </span><span class="hl-identifier">element</span><span class="hl-default">.</span><span class="hl-identifier">text</span></pre></div></div>
<h2><a href="#ReadingXMLAttributes">Reading XML Attributes</a></h2>
<p>Let&#8217;s alter the XML that we are working with to add attributes to the elements and look at how we would parse that information.</p>
<p>If the XML uses attributes in addition to, or instead of, inner text they can be accessed using the Element object&#8217;s <code>attrib</code> attribute.  The <code>attrib</code> attribute is a Python dictionary and is relatively easy to use:</p>
<div class="hl-surround" ><div class="hl-main"><pre><span class="hl-reserved">def </span><span class="hl-identifier">main</span><span class="hl-brackets">()</span><span class="hl-default">:
       </span><span class="hl-identifier">element</span><span class="hl-default"> = </span><span class="hl-identifier">ET</span><span class="hl-default">.</span><span class="hl-identifier">XML</span><span class="hl-brackets">(
               </span><span class="hl-quotes">'</span><span class="hl-string">&lt;root&gt;&lt;child val=&quot;One&quot;/&gt;&lt;child val=&quot;Two&quot;/&gt;&lt;/root&gt;</span><span class="hl-quotes">'</span><span class="hl-brackets">)
       </span><span class="hl-reserved">for </span><span class="hl-identifier">subelement </span><span class="hl-reserved">in </span><span class="hl-identifier">element</span><span class="hl-default">:
               </span><span class="hl-reserved">print </span><span class="hl-identifier">subelement</span><span class="hl-default">.</span><span class="hl-identifier">attrib</span></pre></div></div>
<p>When you run the code you get the following output:</p>
<div class="hl-surround" ><div class="hl-main"><pre><span class="hl-default">{</span><span class="hl-quotes">'</span><span class="hl-string">val</span><span class="hl-quotes">'</span><span class="hl-default">: </span><span class="hl-quotes">'</span><span class="hl-string">One</span><span class="hl-quotes">'</span><span class="hl-default">}
{</span><span class="hl-quotes">'</span><span class="hl-string">val</span><span class="hl-quotes">'</span><span class="hl-default">: </span><span class="hl-quotes">'</span><span class="hl-string">Two</span><span class="hl-quotes">'</span><span class="hl-default">}</span></pre></div></div>
<p>These are the attributes for each child element stored in a dictionary. Being able to work with an XML element&#8217;s attributes as a Python dictionary is a great feature and fits well with the dynamic nature of XML attributes.</p>
<h2><a href="#WritingXML">Writing XML</a></h2>
<p>Now that we&#8217;ve tried our hand at reading XML, let&#8217;s try creating some. If you understand the reading process, you should have no trouble understanding the creation process because it works in much the same manner. What we are going to do in this example is recreate the XML data that we were working with above.</p>
<p>The first step is to create our <code><root></root></code> element:</p>
<div class="hl-surround" ><div class="hl-main"><pre><span class="hl-comment">#create the root &lt;root&gt;
</span><span class="hl-identifier">root_element</span><span class="hl-default"> = </span><span class="hl-identifier">ET</span><span class="hl-default">.</span><span class="hl-identifier">Element</span><span class="hl-brackets">(</span><span class="hl-quotes">&quot;</span><span class="hl-string">root</span><span class="hl-quotes">&quot;</span><span class="hl-brackets">)</span></pre></div></div>
<p>After this code is executed, the variable <code>root_element</code> is an Element object, just like the Element objects that we used earlier to parse the XML.</p>
<p>The next step is to create the two child elements. There are two ways to do this.</p>
<p>In the first method, if you know exactly what you are creating, it&#8217;s easiest to use the <code>SubElement</code> method, which creates an Element object that is a subelement (or child) of another Element object:</p>
<div class="hl-surround" ><div class="hl-main"><pre><span class="hl-comment">#create the first child &lt;child&gt;One&lt;/child&gt;
</span><span class="hl-identifier">child</span><span class="hl-default"> = </span><span class="hl-identifier">ET</span><span class="hl-default">.</span><span class="hl-identifier">SubElement</span><span class="hl-brackets">(</span><span class="hl-identifier">root_element</span><span class="hl-code">, </span><span class="hl-quotes">&quot;</span><span class="hl-string">child</span><span class="hl-quotes">&quot;</span><span class="hl-brackets">)</span></pre></div></div>
<p>This will create a <code><child></child></code> Element that is a child of <code>root_element</code>.  We then need to set the text associated with that element.  To do this we use the same text attribute that we used in the first parsing example. However, instead of simply reading the text attribute we set its value:</p>
<div class="hl-surround" style="height:28px;"><div class="hl-main"><pre><span class="hl-identifier">child</span><span class="hl-default">.</span><span class="hl-identifier">text</span><span class="hl-default"> = </span><span class="hl-quotes">&quot;</span><span class="hl-string">One</span><span class="hl-quotes">&quot;</span></pre></div></div>
<p>The second approach to creating a child element is to create an Element object separately (rather than a sub element) and append it to a parent Element object.  The results are exactly the same &#8211; this is simply a different approach that may come in handy when creating your XML,or working with two sets of XML data.</p>
<p>First we create an Element object in the same way that we created the root element:</p>
<div class="hl-surround" ><div class="hl-main"><pre><span class="hl-comment">#create the second child &lt;child&gt;Two&lt;/child&gt;
</span><span class="hl-identifier">child</span><span class="hl-default"> = </span><span class="hl-identifier">ET</span><span class="hl-default">.</span><span class="hl-identifier">Element</span><span class="hl-brackets">(</span><span class="hl-quotes">&quot;</span><span class="hl-string">child</span><span class="hl-quotes">&quot;</span><span class="hl-brackets">)
</span><span class="hl-identifier">child</span><span class="hl-default">.</span><span class="hl-identifier">text</span><span class="hl-default"> = </span><span class="hl-quotes">&quot;</span><span class="hl-string">Two</span><span class="hl-quotes">&quot;</span></pre></div></div>
<p>This creates the <code>child</code> Element object and sets its text to &#8220;Two&#8221;.  We then append it to the root element: </p>
<div class="hl-surround" ><div class="hl-main"><pre><span class="hl-comment">#now append
</span><span class="hl-identifier">root_element</span><span class="hl-default">.</span><span class="hl-identifier">append</span><span class="hl-brackets">(</span><span class="hl-identifier">child</span><span class="hl-brackets">)</span></pre></div></div>
<p>Pretty simple!  Now, if we want to look at the contents of our <code>root_element</code> (or any other Element object for that matter) we can use the handy <code>tostring</code> function. It does exactly what it says that it does: it converts an Element object into a human readable string.</p>
<div class="hl-surround" ><div class="hl-main"><pre><span class="hl-comment">#Let's see the results
</span><span class="hl-reserved">print </span><span class="hl-identifier">ET</span><span class="hl-default">.</span><span class="hl-identifier">tostring</span><span class="hl-brackets">(</span><span class="hl-identifier">root_element</span><span class="hl-brackets">)</span></pre></div></div>
<p><strong><a href="#Listing3">Listing 3</a></strong></p>
<div class="hl-surround" style="height:280px;"><div class="hl-main"><pre><span class="hl-comment">#!/usr/bin/env python

</span><span class="hl-reserved">from </span><span class="hl-identifier">xml</span><span class="hl-default">.</span><span class="hl-identifier">etree </span><span class="hl-reserved">import </span><span class="hl-identifier">ElementTree as ET

</span><span class="hl-reserved">def </span><span class="hl-identifier">main</span><span class="hl-brackets">()</span><span class="hl-default">:
	</span><span class="hl-comment">#create the root &lt;/root&gt;&lt;root&gt;
	</span><span class="hl-identifier">root_element</span><span class="hl-default"> = </span><span class="hl-identifier">ET</span><span class="hl-default">.</span><span class="hl-identifier">Element</span><span class="hl-brackets">(</span><span class="hl-quotes">&quot;</span><span class="hl-string">root</span><span class="hl-quotes">&quot;</span><span class="hl-brackets">)
	</span><span class="hl-comment">#create the first child &lt;child&gt;One&lt;/child&gt;
	</span><span class="hl-identifier">child</span><span class="hl-default"> = </span><span class="hl-identifier">ET</span><span class="hl-default">.</span><span class="hl-identifier">SubElement</span><span class="hl-brackets">(</span><span class="hl-identifier">root_element</span><span class="hl-code">, </span><span class="hl-quotes">&quot;</span><span class="hl-string">child</span><span class="hl-quotes">&quot;</span><span class="hl-brackets">)
	</span><span class="hl-identifier">child</span><span class="hl-default">.</span><span class="hl-identifier">text</span><span class="hl-default"> = </span><span class="hl-quotes">&quot;</span><span class="hl-string">One</span><span class="hl-quotes">&quot;
	</span><span class="hl-comment">#create the second child &lt;child&gt;Two&lt;/child&gt;
	</span><span class="hl-identifier">child</span><span class="hl-default"> = </span><span class="hl-identifier">ET</span><span class="hl-default">.</span><span class="hl-identifier">Element</span><span class="hl-brackets">(</span><span class="hl-quotes">&quot;</span><span class="hl-string">child</span><span class="hl-quotes">&quot;</span><span class="hl-brackets">)
	</span><span class="hl-identifier">child</span><span class="hl-default">.</span><span class="hl-identifier">text</span><span class="hl-default"> = </span><span class="hl-quotes">&quot;</span><span class="hl-string">Two</span><span class="hl-quotes">&quot;
	</span><span class="hl-comment">#now append
	</span><span class="hl-identifier">root_element</span><span class="hl-default">.</span><span class="hl-identifier">append</span><span class="hl-brackets">(</span><span class="hl-identifier">child</span><span class="hl-brackets">)
	</span><span class="hl-comment">#Let's see the results
	</span><span class="hl-reserved">print </span><span class="hl-identifier">ET</span><span class="hl-default">.</span><span class="hl-identifier">tostring</span><span class="hl-brackets">(</span><span class="hl-identifier">root_element</span><span class="hl-brackets">)

</span><span class="hl-reserved">if </span><span class="hl-identifier">__name__</span><span class="hl-default"> == </span><span class="hl-quotes">&quot;</span><span class="hl-string">__main__</span><span class="hl-quotes">&quot;</span><span class="hl-default">:
	</span><span class="hl-comment"># Someone is launching this directly
	</span><span class="hl-identifier">main</span><span class="hl-brackets">()</span></pre></div></div>
<p>To recap, have a look at the code in Listing 3. When you run this code you will get the following output:</p>
<div class="hl-surround" style="height:28px;"><div class="hl-main"><pre><span class="hl-default">&lt;/</span><span class="hl-identifier">root</span><span class="hl-default">&gt;&lt;</span><span class="hl-identifier">root</span><span class="hl-default">&gt;&lt;</span><span class="hl-identifier">child</span><span class="hl-default">&gt;</span><span class="hl-identifier">One</span><span class="hl-default">&lt;/</span><span class="hl-identifier">child</span><span class="hl-default">&gt;&lt;</span><span class="hl-identifier">child</span><span class="hl-default">&gt;</span><span class="hl-identifier">Two</span><span class="hl-default">&lt;/</span><span class="hl-identifier">child</span><span class="hl-default">&gt;&lt;/</span><span class="hl-identifier">root</span><span class="hl-default">&gt;</span></pre></div></div>
<h2><a href="#WritingXMLAttributes">Writing XML Attributes</a></h2>
<p>If you want to create the XML with attributes (as illustrated in the second reading example), you can use the Element object&#8217;s <code>set</code> method.  To add the <code>val</code> attribute to the first element, use the following:</p>
<div class="hl-surround" style="height:28px;"><div class="hl-main"><pre><span class="hl-identifier">child</span><span class="hl-default">.</span><span class="hl-identifier">set</span><span class="hl-brackets">(</span><span class="hl-quotes">&quot;</span><span class="hl-string">val</span><span class="hl-quotes">&quot;</span><span class="hl-code">,</span><span class="hl-quotes">&quot;</span><span class="hl-string">One</span><span class="hl-quotes">&quot;</span><span class="hl-brackets">)</span></pre></div></div>
<p>You may also set attributes when you create Element objects:</p>
<div class="hl-surround" style="height:28px;"><div class="hl-main"><pre><span class="hl-identifier">child</span><span class="hl-default"> = </span><span class="hl-identifier">ET</span><span class="hl-default">.</span><span class="hl-identifier">Element</span><span class="hl-brackets">(</span><span class="hl-quotes">&quot;</span><span class="hl-string">child</span><span class="hl-quotes">&quot;</span><span class="hl-code">, </span><span class="hl-identifier">val</span><span class="hl-code">=</span><span class="hl-quotes">&quot;</span><span class="hl-string">One</span><span class="hl-quotes">&quot;</span><span class="hl-brackets">)</span></pre></div></div>
<h2><a href="#ReadingXMLFiles">Reading XML Files</a></h2>
<p>Most of the time you won&#8217;t be working with XML data that you explicitly create in your code, instead you will usually read the XML data in from a data source, work with it, and then save it back out when you are done. Fortunately, configuring <em>ElementTree</em> to work with different data sources is very easy.  For example, let&#8217;s take the XML data that we first used and save it into a file named <code>our.xml</code> in the same location as our Python file.</p>
<p>There are a few methods that we can use to load XML data from a file. We are going to use the <code>parse</code> function. This function is nice because it will accept, as a parameter, the path to a file OR a &#8220;file-like&#8221; object.  The term &#8220;file-like&#8221; is used on purpose because the object does not have to be a file object per se &#8211; it simply has to be an object that behaves in a file-like manner. A &#8220;file-like&#8221; object is an object that implements a &#8220;file-like&#8221; interface, meaning that it shares many (if not all) methods with the file object. If an object is &#8220;file-like&#8221; this fact will usually be prominently mentioned in its documentation.</p>
<p>The first thing that we need in order to load the XML data is determine the full path to the <code>our.xml</code> file. In order to calculate this, we determine the full path of our Python source file, strip the filename from it, and then append <code>our.xml</code> to the path. This is rather simple given that the <code>__file__</code> attribute (available in Python 2.2 and later) is the relative path and filename of our Python source file. Although the <code>__file__</code> attribute will be a relative path, we can use it to calculate the absolute path using the standard <em>os</em> module:</p>
<div class="hl-surround" style="height:28px;"><div class="hl-main"><pre><span class="hl-reserved">import </span><span class="hl-identifier">os</span></pre></div></div>
<p>We then call the <code>abspath</code> function to get the absolute path:</p>
<div class="hl-surround" style="height:28px;"><div class="hl-main"><pre><span class="hl-identifier">xml_file</span><span class="hl-default"> = </span><span class="hl-identifier">os</span><span class="hl-default">.</span><span class="hl-identifier">path</span><span class="hl-default">.</span><span class="hl-identifier">abspath</span><span class="hl-brackets">(</span><span class="hl-identifier">__file__</span><span class="hl-brackets">)</span></pre></div></div>
<p>However, since we only want the directory name (not the full path and filename of our Python source file) we have to strip off the filename:</p>
<div class="hl-surround" style="height:28px;"><div class="hl-main"><pre><span class="hl-identifier">xml_file</span><span class="hl-default"> = </span><span class="hl-identifier">os</span><span class="hl-default">.</span><span class="hl-identifier">path</span><span class="hl-default">.</span><span class="hl-identifier">dirname</span><span class="hl-brackets">(</span><span class="hl-identifier">xml_file</span><span class="hl-brackets">)</span></pre></div></div>
<p>Now that we have the directory in which the <code>our.xml</code> file resides, all we have to do is append the <code>our.xml</code> filename to the <code>xml_file</code> variable.  However, instead of just doing something like:</p>
<div class="hl-surround" style="height:28px;"><div class="hl-main"><pre><span class="hl-identifier">xml_file</span><span class="hl-default"> += </span><span class="hl-quotes">&quot;</span><span class="hl-string">/our.xml</span><span class="hl-quotes">&quot;</span></pre></div></div>
<p>we will use the <em>os</em> module to join the two paths so that the resulting path is always correct regardless of what operating system our code is executed on:</p>
<div class="hl-surround" style="height:28px;"><div class="hl-main"><pre><span class="hl-identifier">xml_file</span><span class="hl-default"> = </span><span class="hl-identifier">os</span><span class="hl-default">.</span><span class="hl-identifier">path</span><span class="hl-default">.</span><span class="hl-identifier">join</span><span class="hl-brackets">(</span><span class="hl-identifier">xml_file</span><span class="hl-code">, </span><span class="hl-quotes">&quot;</span><span class="hl-string">our.xml</span><span class="hl-quotes">&quot;</span><span class="hl-brackets">)</span></pre></div></div>
<p><strong>Note</strong>: If you have any trouble understanding what any of the code used to determine the path of <code>our.xml</code> is doing, try printing out <code>xml_file</code> after each of the above lines and it should become clear.</p>
<p>We now have the full path to the <code>our.xml</code> file.  In order to load its XML data we simply pass the path to the <code>parse</code> function:</p>
<div class="hl-surround" style="height:28px;"><div class="hl-main"><pre><span class="hl-identifier">tree</span><span class="hl-default"> = </span><span class="hl-identifier">ET</span><span class="hl-default">.</span><span class="hl-identifier">parse</span><span class="hl-brackets">(</span><span class="hl-identifier">xml_file</span><span class="hl-brackets">)</span></pre></div></div>
<p>We now have an ElementTree object instance that represents our XML file.</p>
<p>Since we are working with files, we should watch out for incorrect paths, I/O errors, or the parse function failing for any other reason.  If you wish to be extra careful, you can wrap the parse function in a try/except block in order to catch any exceptions that may be thrown:</p>
<div class="hl-surround" ><div class="hl-main"><pre><span class="hl-reserved">try</span><span class="hl-default">:
       </span><span class="hl-identifier">tree</span><span class="hl-default"> = </span><span class="hl-identifier">ET</span><span class="hl-default">.</span><span class="hl-identifier">parse</span><span class="hl-brackets">(</span><span class="hl-quotes">&quot;</span><span class="hl-string">sar</span><span class="hl-quotes">&quot;</span><span class="hl-brackets">)
</span><span class="hl-reserved">except Exception</span><span class="hl-default">, </span><span class="hl-identifier">inst</span><span class="hl-default">:
       </span><span class="hl-reserved">print </span><span class="hl-quotes">&quot;</span><span class="hl-string">Unexpected error opening %s: %s</span><span class="hl-quotes">&quot;</span><span class="hl-default"> % </span><span class="hl-brackets">(</span><span class="hl-identifier">xml_file</span><span class="hl-code">, </span><span class="hl-identifier">inst</span><span class="hl-brackets">)
       </span><span class="hl-reserved">return</span></pre></div></div>
<p>In the except block, I catch the Exception base class so that I catch any and all exceptions that may be thrown (in the case of a missing file it will most likely be an <code>IOError</code> exception).</p>
<h2><a href="#WritingXMLDatatoaFile">Writing XML Data to a File</a></h2>
<p>Now that we know how to read in XML data, we should look at how one writes XML data out to a file.  Let&#8217;s assume that after reading in the <code>out.xml</code> fiie we want to add another item to the XML file that we just read in:</p>
<div class="hl-surround" ><div class="hl-main"><pre><span class="hl-identifier">child</span><span class="hl-default"> = </span><span class="hl-identifier">ET</span><span class="hl-default">.</span><span class="hl-identifier">SubElement</span><span class="hl-brackets">(</span><span class="hl-identifier">tree</span><span class="hl-code">.</span><span class="hl-identifier">getroot</span><span class="hl-brackets">()</span><span class="hl-code">, </span><span class="hl-quotes">&quot;</span><span class="hl-string">child</span><span class="hl-quotes">&quot;</span><span class="hl-brackets">)
</span><span class="hl-identifier">child</span><span class="hl-default">.</span><span class="hl-identifier">text</span><span class="hl-default"> = </span><span class="hl-quotes">&quot;</span><span class="hl-string">Three</span><span class="hl-quotes">&quot;</span></pre></div></div>
<p>Notice that in order to add a child to the root element we used the ElementTree object&#8217;s <code>getroot</code> function. The <code>getroot</code> function simply returns the root Element object of the XML data.</p>
<p>Now that we have a third child element, let&#8217;s write the XML data back out to <code>our.xml</code>. Thanks to <em>ElementTree</em> this is a painless experience:</p>
<div class="hl-surround" style="height:28px;"><div class="hl-main"><pre><span class="hl-identifier">tree</span><span class="hl-default">.</span><span class="hl-identifier">write</span><span class="hl-brackets">(</span><span class="hl-identifier">xml_file</span><span class="hl-brackets">)</span></pre></div></div>
<p>That&#8217;s it!</p>
<p>If we want to be really careful when writing the XML data out to a file, we&#8217;ll watch out for exceptions. However most of the time the <code>write</code> method will succeed without throwing an exception; it is more important to be sure that the path used is correct.  Often times, instead of getting the exception that you want, you end up with an XML file stored in some far off and strange location on your hard drive because your path was incorrect or you did not specify the full path.  But, as is often the case when programming, better safe than sorry:</p>
<div class="hl-surround" ><div class="hl-main"><pre><span class="hl-reserved">try</span><span class="hl-default">:
       </span><span class="hl-identifier">tree</span><span class="hl-default">.</span><span class="hl-identifier">write</span><span class="hl-brackets">(</span><span class="hl-identifier">xml_file</span><span class="hl-brackets">)
</span><span class="hl-reserved">except Exception</span><span class="hl-default">, </span><span class="hl-identifier">inst</span><span class="hl-default">:
       </span><span class="hl-reserved">print </span><span class="hl-quotes">&quot;</span><span class="hl-string">Unexpected error writing to file %s: %s</span><span class="hl-quotes">&quot;</span><span class="hl-default"> % </span><span class="hl-brackets">(</span><span class="hl-identifier">xml_file</span><span class="hl-code">, </span><span class="hl-identifier">inst</span><span class="hl-brackets">)
       </span><span class="hl-reserved">return</span></pre></div></div>
<p>To recap you can find all of the code from this section in Listing 4.</p>
<p><strong><a href="#Listing4">Listing 4</a></strong></p>
<div class="hl-surround" style="height:280px;"><div class="hl-main"><pre><span class="hl-comment">#!/usr/bin/env python

</span><span class="hl-reserved">from </span><span class="hl-identifier">xml</span><span class="hl-default">.</span><span class="hl-identifier">etree </span><span class="hl-reserved">import </span><span class="hl-identifier">ElementTree as ET
</span><span class="hl-reserved">import </span><span class="hl-identifier">os

</span><span class="hl-reserved">def </span><span class="hl-identifier">main</span><span class="hl-brackets">()</span><span class="hl-default">:

	</span><span class="hl-identifier">xml_file</span><span class="hl-default"> = </span><span class="hl-identifier">os</span><span class="hl-default">.</span><span class="hl-identifier">path</span><span class="hl-default">.</span><span class="hl-identifier">abspath</span><span class="hl-brackets">(</span><span class="hl-identifier">__file__</span><span class="hl-brackets">)
	</span><span class="hl-identifier">xml_file</span><span class="hl-default"> = </span><span class="hl-identifier">os</span><span class="hl-default">.</span><span class="hl-identifier">path</span><span class="hl-default">.</span><span class="hl-identifier">dirname</span><span class="hl-brackets">(</span><span class="hl-identifier">xml_file</span><span class="hl-brackets">)
	</span><span class="hl-identifier">xml_file</span><span class="hl-default"> = </span><span class="hl-identifier">os</span><span class="hl-default">.</span><span class="hl-identifier">path</span><span class="hl-default">.</span><span class="hl-identifier">join</span><span class="hl-brackets">(</span><span class="hl-identifier">xml_file</span><span class="hl-code">, </span><span class="hl-quotes">&quot;</span><span class="hl-string">our.xml</span><span class="hl-quotes">&quot;</span><span class="hl-brackets">)

	</span><span class="hl-reserved">try</span><span class="hl-default">:
		</span><span class="hl-identifier">tree</span><span class="hl-default"> = </span><span class="hl-identifier">ET</span><span class="hl-default">.</span><span class="hl-identifier">parse</span><span class="hl-brackets">(</span><span class="hl-identifier">xml_file</span><span class="hl-brackets">)
	</span><span class="hl-reserved">except Exception</span><span class="hl-default">, </span><span class="hl-identifier">inst</span><span class="hl-default">:
		</span><span class="hl-reserved">print </span><span class="hl-quotes">&quot;</span><span class="hl-string">Unexpected error opening %s: %s</span><span class="hl-quotes">&quot;</span><span class="hl-default"> % </span><span class="hl-brackets">(</span><span class="hl-identifier">xml_file</span><span class="hl-code">, </span><span class="hl-identifier">inst</span><span class="hl-brackets">)
		</span><span class="hl-reserved">return

	</span><span class="hl-identifier">child</span><span class="hl-default"> = </span><span class="hl-identifier">ET</span><span class="hl-default">.</span><span class="hl-identifier">SubElement</span><span class="hl-brackets">(</span><span class="hl-identifier">tree</span><span class="hl-code">.</span><span class="hl-identifier">getroot</span><span class="hl-brackets">()</span><span class="hl-code">, </span><span class="hl-quotes">&quot;</span><span class="hl-string">child</span><span class="hl-quotes">&quot;</span><span class="hl-brackets">)
	</span><span class="hl-identifier">child</span><span class="hl-default">.</span><span class="hl-identifier">text</span><span class="hl-default"> = </span><span class="hl-quotes">&quot;</span><span class="hl-string">Three</span><span class="hl-quotes">&quot;

	</span><span class="hl-reserved">try</span><span class="hl-default">:
		</span><span class="hl-identifier">tree</span><span class="hl-default">.</span><span class="hl-identifier">write</span><span class="hl-brackets">(</span><span class="hl-identifier">xml_file</span><span class="hl-brackets">)
	</span><span class="hl-reserved">except Exception</span><span class="hl-default">, </span><span class="hl-identifier">inst</span><span class="hl-default">:
		</span><span class="hl-reserved">print </span><span class="hl-quotes">&quot;</span><span class="hl-string">Unexpected error writing to file %s: %s</span><span class="hl-quotes">&quot;</span><span class="hl-default"> % </span><span class="hl-brackets">(</span><span class="hl-identifier">xml_file</span><span class="hl-code">, </span><span class="hl-identifier">inst</span><span class="hl-brackets">)
		</span><span class="hl-reserved">return

if </span><span class="hl-identifier">__name__</span><span class="hl-default"> == </span><span class="hl-quotes">&quot;</span><span class="hl-string">__main__</span><span class="hl-quotes">&quot;</span><span class="hl-default">:
	</span><span class="hl-comment"># Someone is launching this directly
	</span><span class="hl-identifier">main</span><span class="hl-brackets">()</span></pre></div></div>
<p>When you run the code and take a look at the <code>our.xml</code> file you should see that the the third child element has been added:</p>
<div class="hl-surround" ><div class="hl-main"><pre><span class="hl-default">&lt;</span><span class="hl-identifier">root</span><span class="hl-default">&gt;
&lt;</span><span class="hl-identifier">child</span><span class="hl-default">&gt;</span><span class="hl-identifier">One</span><span class="hl-default">&lt;/</span><span class="hl-identifier">child</span><span class="hl-default">&gt;
&lt;</span><span class="hl-identifier">child</span><span class="hl-default">&gt;</span><span class="hl-identifier">Two</span><span class="hl-default">&lt;/</span><span class="hl-identifier">child</span><span class="hl-default">&gt;
&lt;</span><span class="hl-identifier">child</span><span class="hl-default">&gt;</span><span class="hl-identifier">Three</span><span class="hl-default">&lt;/</span><span class="hl-identifier">child</span><span class="hl-default">&gt;
&lt;/</span><span class="hl-identifier">root</span><span class="hl-default">&gt;</span></pre></div></div>
<h2><a href="#ReadingfromtheWeb">Reading from the Web</a></h2>
<p>Working with a local file is very useful, but you might also be in a situation where you will have to work with an XML file that is located on the Internet, perhaps an RSS feed.  Fortunately, since the <code>parse</code> function explained above works with file-like elements, loading a URL is very easy.</p>
<p>First off, you need to import the <em>urllib</em> module; a standard module that allows you to open URLs in a method similar to opening local files:</p>
<div class="hl-surround" style="height:28px;"><div class="hl-main"><pre><span class="hl-reserved">import </span><span class="hl-identifier">urllib</span></pre></div></div>
<p>In order to open a URL we use:</p>
<div class="hl-surround" ><div class="hl-main"><pre><span class="hl-identifier">feed</span><span class="hl-default"> = </span><span class="hl-identifier">urllib</span><span class="hl-default">.</span><span class="hl-identifier">urlopen</span><span class="hl-brackets">(</span><span class="hl-quotes">&quot;</span><span class="hl-string">http://pythonmagazine.com/c/news/atom</span><span class="hl-quotes">&quot;</span><span class="hl-brackets">)
</span><span class="hl-identifier">tree</span><span class="hl-default"> = </span><span class="hl-identifier">ET</span><span class="hl-default">.</span><span class="hl-identifier">parse</span><span class="hl-brackets">(</span><span class="hl-identifier">feed</span><span class="hl-brackets">)</span></pre></div></div>
<h2><a href="#Conclusion">Conclusion</a></h2>
<p>And that&#8217;s that!  This concludes our brief introduction to XML parsing using the <em>ElementTree</em> module. Hopefully throughout this article you have seen how easy it is to create and manipulate XML using <em>ElementTree</em> &#8230;and I&#8217;ve only scratched the surface.  For more information take a look at the official Python documentation and some of the great examples on the effbot website. I&#8217;m sure you&#8217;ll be an XML wizard in no time.</p>
<p>[1] <a href="http://docs.python.org/whatsnew/modules.html#SECTION0001420000000000000000">http://docs.python.org/whatsnew/modules.html#SECTION0001420000000000000000</a><br />
[2] <a href="http://effbot.org/zone/pythondoc-elementtree-ElementTree.htm#elementtree.ElementTree.XML-function">http://effbot.org/zone/pythondoc-elementtree-ElementTree.htm#elementtree.ElementTree.XML-function</a><br />
[3] <a href="http://effbot.org/zone/pythondoc-elementtree-ElementTree.htm#elementtree.ElementTree.ElementTree-class">http://effbot.org/zone/pythondoc-elementtree-ElementTree.htm#elementtree.ElementTree.ElementTree-class</a></p>
<div style="float:right;margin:0px 0px 0px 0px;"><a href="http://www.google.com/reader/link?url=http://www.learningpython.com/2008/05/07/elegant-xml-parsing-using-the-elementtree-module/&title=Elegant XML parsing using the ElementTree Module&srcTitle=learning python&srcURL=http://www.learningpython.com"target="_blank" rel=""><img border="0" src="http://www.learningpython.com/wp-content/plugins/wp-google-buzz/icon/12.png" style="opacity:1;filter:alpha(opacity=100)" onmouseover="this.style.opacity=0.8;this.filters.alpha.opacity=70" onmouseout="this.style.opacity=1;this.filters.alpha.opacity=100"/> </a></div>]]></content:encoded>
			<wfw:commentRss>http://www.learningpython.com/2008/05/07/elegant-xml-parsing-using-the-elementtree-module/feed/</wfw:commentRss>
		<slash:comments>12</slash:comments>
		</item>
		<item>
		<title>Level Editor 0.2</title>
		<link>http://www.learningpython.com/2008/04/01/level-editor-02/</link>
		<comments>http://www.learningpython.com/2008/04/01/level-editor-02/#comments</comments>
		<pubDate>Wed, 02 Apr 2008 02:03:31 +0000</pubDate>
		<dc:creator>selsine</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[game engine]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[games]]></category>
		<category><![CDATA[level editor]]></category>

		<guid isPermaLink="false">http://www.learningpython.com/?p=73</guid>
		<description><![CDATA[
			
				
			
		
So I had some free time since I last posted so I hacked a little bit more into my simple game editor. I&#8217;ve a few things in there that I wanted to get in:

A grid
A paint mode to easily add sprites
An erase mode so that sprites can be removed
Fully (or so it seems) working property [...]]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style="float: right; margin-left: 10px;">
			<a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fwww.learningpython.com%2F2008%2F04%2F01%2Flevel-editor-02%2F"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fwww.learningpython.com%2F2008%2F04%2F01%2Flevel-editor-02%2F&amp;style=normal" height="61" width="50" /><br />
			</a>
		</div>
<p>So I had some free time since I last posted so I hacked a little bit more into my simple game editor. I&#8217;ve a few things in there that I wanted to get in:</p>
<ul>
<li>A grid</li>
<li>A paint mode to easily add sprites</li>
<li>An erase mode so that sprites can be removed</li>
<li>Fully (or so it seems) working property addition to the sprites</li>
<li>Added some organization to the code. I was hacking on this enough that putting things in their right spot started to make more and more sense.</li>
<li>Started to use mercurial to keep track of source changes. I know how important version control is, and after making a silly mistake I decided that I wanted to start using it with this project.</li>
</ul>
<p>You can take a look at how things are working here: </p>
<p><a href="http://www.learningpython.com/images/dodger/editor_02.png"><img style="margin: 0pt 10px 10px 0pt;" src="http://www.learningpython.com/images/dodger/editor_02.png" alt="Python Game pyglet editor" border="0"/><img /></a></p>
<p>It&#8217;s not pretty yet, but it&#8217;s coming along.</p>
<div style="float:right;margin:0px 0px 0px 0px;"><a href="http://www.google.com/reader/link?url=http://www.learningpython.com/2008/04/01/level-editor-02/&title=Level Editor 0.2&srcTitle=learning python&srcURL=http://www.learningpython.com"target="_blank" rel=""><img border="0" src="http://www.learningpython.com/wp-content/plugins/wp-google-buzz/icon/12.png" style="opacity:1;filter:alpha(opacity=100)" onmouseover="this.style.opacity=0.8;this.filters.alpha.opacity=70" onmouseout="this.style.opacity=1;this.filters.alpha.opacity=100"/> </a></div>]]></content:encoded>
			<wfw:commentRss>http://www.learningpython.com/2008/04/01/level-editor-02/feed/</wfw:commentRss>
		<slash:comments>13</slash:comments>
		</item>
		<item>
		<title>Pyglet Level Editor</title>
		<link>http://www.learningpython.com/2008/03/22/pyglet-level-editor/</link>
		<comments>http://www.learningpython.com/2008/03/22/pyglet-level-editor/#comments</comments>
		<pubDate>Sat, 22 Mar 2008 18:18:04 +0000</pubDate>
		<dc:creator>selsine</dc:creator>
				<category><![CDATA[PyGlet]]></category>
		<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[game engine]]></category>
		<category><![CDATA[python]]></category>

		<guid isPermaLink="false">http://www.learningpython.com/?p=72</guid>
		<description><![CDATA[
			
				
			
		
Hey Everyone,
Sorry I&#8217;ve been away for a bit, work and trips and writing for Python Magazine had me pretty busy and I wasn&#8217;t able to reply to everyone&#8217;s comments on the simple Python game engine. I really do appreciate the comments though so please keep them coming.
I have been thinking about the simple game engine [...]]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style="float: right; margin-left: 10px;">
			<a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fwww.learningpython.com%2F2008%2F03%2F22%2Fpyglet-level-editor%2F"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fwww.learningpython.com%2F2008%2F03%2F22%2Fpyglet-level-editor%2F&amp;style=normal" height="61" width="50" /><br />
			</a>
		</div>
<p>Hey Everyone,</p>
<p>Sorry I&#8217;ve been away for a bit, work and trips and writing for Python Magazine had me pretty busy and I wasn&#8217;t able to reply to everyone&#8217;s comments on the simple Python game engine. I really do appreciate the comments though so please keep them coming.</p>
<p>I have been thinking about the simple game engine quite a bit though and wondering where to start on it all, and whether or not it makes sense to start on it at all!  After some thinking I decided that what I would want most (for a variety of reasons) would be an easy to use level editor. So with a day off from work and life yesterday I started to do some hacking with PyGTK and pyglet to see if I couldn&#8217;t get a simple level editor going.</p>
<p>The results are still quite crude, but the basics are starting to get in there:</p>
<p><a href="http://www.learningpython.com/images/dodger/editor.png"><img style="margin: 0pt 10px 10px 0pt;" src="http://www.learningpython.com/images/dodger/editor.png" alt="Python Game pyglet editor" border="0"/><img /></a></p>
<p>As you can see it&#8217;s a PyGTK application with an OpenGL window that displays pyglet sprites. There is a properties list, where you can add and edit properties or the sprite. There is also a &#8220;content&#8221; list that displays all of the graphics in your project&#8217;s &#8220;content&#8221; directory. Then you can add any of those images to your level. You can also select sprites and move them around, or edit their properties (notice the monster with the yellow border around it?).</p>
<p>The idea is that eventually this will save the information out into a human readable file type (yaml, xml, whatever) that games (your game?) will then read in for their levels. The properties will be saved with each sprite and then applied when you load the level. That way you can add specific properties to specific sprites.</p>
<p>This is still very much a work in progress, but when it gets a little bit more stable and if people are interested I think I&#8217;ll create a project on sourceforge or google code so the other people can start working with it or hacking it.</p>
<p>So&#8230;ideas? Comments? Thoughts?</p>
<div style="float:right;margin:0px 0px 0px 0px;"><a href="http://www.google.com/reader/link?url=http://www.learningpython.com/2008/03/22/pyglet-level-editor/&title=Pyglet Level Editor&srcTitle=learning python&srcURL=http://www.learningpython.com"target="_blank" rel=""><img border="0" src="http://www.learningpython.com/wp-content/plugins/wp-google-buzz/icon/12.png" style="opacity:1;filter:alpha(opacity=100)" onmouseover="this.style.opacity=0.8;this.filters.alpha.opacity=70" onmouseout="this.style.opacity=1;this.filters.alpha.opacity=100"/> </a></div>]]></content:encoded>
			<wfw:commentRss>http://www.learningpython.com/2008/03/22/pyglet-level-editor/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>I&#8217;m still here</title>
		<link>http://www.learningpython.com/2008/01/24/im-still-here/</link>
		<comments>http://www.learningpython.com/2008/01/24/im-still-here/#comments</comments>
		<pubDate>Fri, 25 Jan 2008 02:18:50 +0000</pubDate>
		<dc:creator>selsine</dc:creator>
				<category><![CDATA[News]]></category>
		<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://www.learningpython.com/2008/01/24/im-still-here/</guid>
		<description><![CDATA[
			
				
			
		
No I&#8217;m not dead&#8230;even after the recent car accident&#8230;.I&#8217;ve just been busy. Busy writing for columns for the monthly Python Magazine. But that does not mean that his blog is dead! In fact I&#8217;ve been spending the last hour looking around the web for something new and cool in the world of Python.
I&#8217;m looking for [...]]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style="float: right; margin-left: 10px;">
			<a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fwww.learningpython.com%2F2008%2F01%2F24%2Fim-still-here%2F"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fwww.learningpython.com%2F2008%2F01%2F24%2Fim-still-here%2F&amp;style=normal" height="61" width="50" /><br />
			</a>
		</div>
<p>No I&#8217;m not dead&#8230;even after the recent car accident&#8230;.I&#8217;ve just been busy. Busy writing for columns for the monthly <a href="http://pymag.phparch.com/">Python Magazine</a>. But that does not mean that his blog is dead! In fact I&#8217;ve been spending the last hour looking around the web for something new and cool in the world of Python.</p>
<p>I&#8217;m looking for something new to sink my teeth into, something different. I&#8217;m looking forward to Python 3000, I&#8217;ve been trying to keep up with many of the changes and so far it&#8217;s looking really good. But in the mean time there must be something happening in the far off corners of the Python world&#8230;where someone is doing something extremely cool.</p>
<p>Please if you have an idea let me know, send me an email, or add a comment to this post. Is there anything that you want me to cover here? A tutorial that you would like? A tutorial that you have written? A new module you wrote?  Whatever it is let me know! A new visualization tool? More Python on the web?</p>
<p>I&#8217;ve been spending too much time in the world of C++ lately and I&#8217;m hungry for some Python&#8230;</p>
<div style="float:right;margin:0px 0px 0px 0px;"><a href="http://www.google.com/reader/link?url=http://www.learningpython.com/2008/01/24/im-still-here/&title=I'm still here&srcTitle=learning python&srcURL=http://www.learningpython.com"target="_blank" rel=""><img border="0" src="http://www.learningpython.com/wp-content/plugins/wp-google-buzz/icon/12.png" style="opacity:1;filter:alpha(opacity=100)" onmouseover="this.style.opacity=0.8;this.filters.alpha.opacity=70" onmouseout="this.style.opacity=1;this.filters.alpha.opacity=100"/> </a></div>]]></content:encoded>
			<wfw:commentRss>http://www.learningpython.com/2008/01/24/im-still-here/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>Creating a game with PyGlet and Python</title>
		<link>http://www.learningpython.com/2007/11/10/creating-a-game-with-pyglet-and-python/</link>
		<comments>http://www.learningpython.com/2007/11/10/creating-a-game-with-pyglet-and-python/#comments</comments>
		<pubDate>Sat, 10 Nov 2007 18:31:44 +0000</pubDate>
		<dc:creator>selsine</dc:creator>
				<category><![CDATA[PyGlet]]></category>
		<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[python]]></category>

		<guid isPermaLink="false">http://www.learningpython.com/?p=67</guid>
		<description><![CDATA[
			
				
			
		
For this tutorial I&#8217;m going to take a look at PyGlet: &#8220;a cross-platform windowing and multimedia library for Python.&#8221; The reason that I decided to take a look at PyGlet is because it is an alternative to PyGame in the Python gaming world and: &#8220;No external dependencies or installation requirements. For most application and game [...]]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style="float: right; margin-left: 10px;">
			<a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fwww.learningpython.com%2F2007%2F11%2F10%2Fcreating-a-game-with-pyglet-and-python%2F"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fwww.learningpython.com%2F2007%2F11%2F10%2Fcreating-a-game-with-pyglet-and-python%2F&amp;style=normal" height="61" width="50" /><br />
			</a>
		</div>
<p>For this tutorial I&#8217;m going to take a look at PyGlet: &#8220;a cross-platform windowing and multimedia library for Python.&#8221; The reason that I decided to take a look at PyGlet is because it is an alternative to PyGame in the Python gaming world and: &#8220;No external dependencies or installation requirements. For most application and game requirements, pyglet needs nothing else besides Python, simplifying distribution and installation.&#8221;[1]</p>
<p>The first step to using PyGlet is to actually download it and install it (http://pyglet.org/download.html) as of writing this PyGlet is at version 1.0 alpha 2 (as I finished this tutorial Beta 1 was released but I have been unable to try it out), so between now and the final release there are bound to be a few changes. Once you have download the correct version for your system install it an you are ready to go. I&#8217;m writing this on a Debian box so I downloaded the source distribution and 	installed it using the following, as per the instructions:</p>
<p><code><br />
python setup.py install<br />
</code></p>
<p>Now like PyGame, PyGlet is a framework for developing games or other applications, it is not a game engine, therefore if you are looking to create a full game you will need to create your own, or use someone else&#8217;s. This tutorial will not going into full game creation, instead it will introduce PyGlet using a small sample application, hopefully giving you enough of the basics, or enough of a taste to continue on with it.</p>
<p>You can download the full source to this tutorial <a href="http://www.learningpython.com/sources/pygletSpace.tar.gz">here</a>.</p>
<p><img style="margin: 0pt 10px 10px 0pt;" src="http://www.learningpython.com/images/pyglet_01/pyglet_02.png" alt="Python Game PyGlet" border="0"/><br />
<img /></p>
<p><span id="more-67"></span></p>
<h2>Creating a Window</h2>
<p>The first step is to get an actual window displaying. In this initial code I&#8217;m going to create a window with a main game loop and display the Frames Per Second that the game is currently running at. In order to do this I am going to subclass from the <a href="http://pyglet.org/doc/api/pyglet.window.Window-class.html">pyglet.window.Window</a> class. You don&#8217;t have to do this in order to display a window, but given the way that events are handled this seemed to make the most sense to me.</p>
<p>I added the following to a file named &#8220;PyGletSpace.py&#8221;</p>
<div class="hl-surround" style="height:280px;"><div class="hl-main"><pre><span class="hl-reserved">from </span><span class="hl-identifier">pyglet </span><span class="hl-reserved">import </span><span class="hl-identifier">window
</span><span class="hl-reserved">from </span><span class="hl-identifier">pyglet </span><span class="hl-reserved">import </span><span class="hl-identifier">clock
</span><span class="hl-reserved">from </span><span class="hl-identifier">pyglet </span><span class="hl-reserved">import </span><span class="hl-identifier">font

</span><span class="hl-reserved">class </span><span class="hl-identifier">SpaceGameWindow</span><span class="hl-brackets">(</span><span class="hl-identifier">window</span><span class="hl-code">.</span><span class="hl-identifier">Window</span><span class="hl-brackets">)</span><span class="hl-default">:

	</span><span class="hl-reserved">def </span><span class="hl-identifier">__init__</span><span class="hl-brackets">(</span><span class="hl-identifier">self</span><span class="hl-code">, *</span><span class="hl-identifier">args</span><span class="hl-code">, **</span><span class="hl-identifier">kwargs</span><span class="hl-brackets">)</span><span class="hl-default">:

		</span><span class="hl-comment">#Let all of the standard stuff pass through
		</span><span class="hl-identifier">window</span><span class="hl-default">.</span><span class="hl-identifier">Window</span><span class="hl-default">.</span><span class="hl-identifier">__init__</span><span class="hl-brackets">(</span><span class="hl-identifier">self</span><span class="hl-code">, *</span><span class="hl-identifier">args</span><span class="hl-code">, **</span><span class="hl-identifier">kwargs</span><span class="hl-brackets">)

	</span><span class="hl-reserved">def </span><span class="hl-identifier">main_loop</span><span class="hl-brackets">(</span><span class="hl-identifier">self</span><span class="hl-brackets">)</span><span class="hl-default">:

		</span><span class="hl-comment">#Create a font for our FPS clock
		</span><span class="hl-identifier">ft</span><span class="hl-default"> = </span><span class="hl-identifier">font</span><span class="hl-default">.</span><span class="hl-identifier">load</span><span class="hl-brackets">(</span><span class="hl-quotes">'</span><span class="hl-string">Arial</span><span class="hl-quotes">'</span><span class="hl-code">, </span><span class="hl-number">28</span><span class="hl-brackets">)
		</span><span class="hl-comment">#The pyglet.font.Text object to display the FPS
		</span><span class="hl-identifier">fps_text</span><span class="hl-default"> = </span><span class="hl-identifier">font</span><span class="hl-default">.</span><span class="hl-identifier">Text</span><span class="hl-brackets">(</span><span class="hl-identifier">ft</span><span class="hl-code">, </span><span class="hl-identifier">y</span><span class="hl-code">=</span><span class="hl-number">10</span><span class="hl-brackets">)

		</span><span class="hl-reserved">while not </span><span class="hl-identifier">self</span><span class="hl-default">.</span><span class="hl-identifier">has_exit</span><span class="hl-default">:
			</span><span class="hl-identifier">self</span><span class="hl-default">.</span><span class="hl-identifier">dispatch_events</span><span class="hl-brackets">()
			</span><span class="hl-identifier">self</span><span class="hl-default">.</span><span class="hl-identifier">clear</span><span class="hl-brackets">()

			</span><span class="hl-comment">#Tick the clock
			</span><span class="hl-identifier">clock</span><span class="hl-default">.</span><span class="hl-identifier">tick</span><span class="hl-brackets">()
			</span><span class="hl-comment">#Gets fps and draw it
			</span><span class="hl-identifier">fps_text</span><span class="hl-default">.</span><span class="hl-identifier">text</span><span class="hl-default"> = </span><span class="hl-brackets">(</span><span class="hl-quotes">&quot;</span><span class="hl-string">fps: %d</span><span class="hl-quotes">&quot;</span><span class="hl-brackets">)</span><span class="hl-default"> % </span><span class="hl-brackets">(</span><span class="hl-identifier">clock</span><span class="hl-code">.</span><span class="hl-identifier">get_fps</span><span class="hl-brackets">())
			</span><span class="hl-identifier">fps_text</span><span class="hl-default">.</span><span class="hl-identifier">draw</span><span class="hl-brackets">()

			</span><span class="hl-identifier">self</span><span class="hl-default">.</span><span class="hl-identifier">flip</span><span class="hl-brackets">()

</span><span class="hl-reserved">if </span><span class="hl-identifier">__name__</span><span class="hl-default"> == </span><span class="hl-quotes">&quot;</span><span class="hl-string">__main__</span><span class="hl-quotes">&quot;</span><span class="hl-default">:
	</span><span class="hl-comment"># Someone is launching this directly
	</span><span class="hl-identifier">space</span><span class="hl-default"> = </span><span class="hl-identifier">SpaceGameWindow</span><span class="hl-brackets">()
	</span><span class="hl-identifier">space</span><span class="hl-default">.</span><span class="hl-identifier">main_loop</span><span class="hl-brackets">()</span></pre></div></div>
<p>So we are not doing anything that fancy here, first we import three things from the PyGlet library, the window, clock, and font modules. We then create a class called SpaceGameWindow which is a subclass of the <a href="http://pyglet.org/doc/api/pyglet.window.Window-class.html">pyglet.window.Window</a> class. </p>
<p>Then we have a simple initialization function where for now we simply pass all of the keywords and arguments to the pyglet.window.Window&#8217;s __init__() function. </p>
<p>Next we have our main_loop() function which will serve as the main loop for the game. Here we create a <a href="http://pyglet.org/doc/api/pyglet.font.base.Font-class.html">pyglet.font.base.Font</a> object and a <a href="http://pyglet.org/doc/api/pyglet.font.Text-class.html">pyglet.font.Text</a> object that will serve as the font for our &#8220;Frames Per Second&#8221; text, and the class that will actually write out the &#8220;Frames Per Second&#8221; text.</p>
<p>After that we have the actual game loop where we continue to loop until the window&#8217;s has_exit boolean member variable becomes true.</p>
<p>In the loop we first dispatch all of the event to the event handlers, and then we clear the window to prepare it for drawing.  Then we tick the clock, get our FPS text and then draw it out to the screen.  Then, since windows in PyGlet are double buffered we flip the display.</p>
<p>Hopefully that is pretty straight forward, if you run the code you should see something similar to the following:</p>
<p><img style="margin: 0pt 10px 10px 0pt;" src="http://www.learningpython.com/images/pyglet_01/pyglet_01.png" alt="Python Game PyGlet" border="0"/><br />
<img /></p>
<h2>Sprites</h2>
<p>Pretty good so far but this doesn&#8217;t really help us or do anything, so the next step is to get some stuff draw onto the screen. To do that I&#8217;m going to create a simple Sprite class.  This class will be loosely based off of the PyGame&#8217;s Sprite class, but for the most part will serve as a helper for drawing and the action on the screen.</p>
<div class="hl-surround" style="height:280px;"><div class="hl-main"><pre><span class="hl-reserved">class </span><span class="hl-identifier">Sprite</span><span class="hl-brackets">(</span><span class="hl-identifier">object</span><span class="hl-brackets">)</span><span class="hl-default">:

	</span><span class="hl-reserved">def </span><span class="hl-identifier">__get_left</span><span class="hl-brackets">(</span><span class="hl-identifier">self</span><span class="hl-brackets">)</span><span class="hl-default">:
		</span><span class="hl-reserved">return </span><span class="hl-identifier">self</span><span class="hl-default">.</span><span class="hl-identifier">x
	left</span><span class="hl-default"> = </span><span class="hl-builtin">property</span><span class="hl-brackets">(</span><span class="hl-identifier">__get_left</span><span class="hl-brackets">)

	</span><span class="hl-reserved">def </span><span class="hl-identifier">__get_right</span><span class="hl-brackets">(</span><span class="hl-identifier">self</span><span class="hl-brackets">)</span><span class="hl-default">:
		</span><span class="hl-reserved">return </span><span class="hl-identifier">self</span><span class="hl-default">.</span><span class="hl-identifier">x</span><span class="hl-default"> + </span><span class="hl-identifier">self</span><span class="hl-default">.</span><span class="hl-identifier">image</span><span class="hl-default">.</span><span class="hl-identifier">width
	right</span><span class="hl-default"> = </span><span class="hl-builtin">property</span><span class="hl-brackets">(</span><span class="hl-identifier">__get_right</span><span class="hl-brackets">)

	</span><span class="hl-reserved">def </span><span class="hl-identifier">__get_top</span><span class="hl-brackets">(</span><span class="hl-identifier">self</span><span class="hl-brackets">)</span><span class="hl-default">:
		</span><span class="hl-reserved">return </span><span class="hl-identifier">self</span><span class="hl-default">.</span><span class="hl-identifier">y</span><span class="hl-default"> + </span><span class="hl-identifier">self</span><span class="hl-default">.</span><span class="hl-identifier">image</span><span class="hl-default">.</span><span class="hl-identifier">height
	top</span><span class="hl-default"> = </span><span class="hl-builtin">property</span><span class="hl-brackets">(</span><span class="hl-identifier">__get_top</span><span class="hl-brackets">)

	</span><span class="hl-reserved">def </span><span class="hl-identifier">__get_bottom</span><span class="hl-brackets">(</span><span class="hl-identifier">self</span><span class="hl-brackets">)</span><span class="hl-default">:
		</span><span class="hl-reserved">return </span><span class="hl-identifier">self</span><span class="hl-default">.</span><span class="hl-identifier">y
	bottom</span><span class="hl-default"> = </span><span class="hl-builtin">property</span><span class="hl-brackets">(</span><span class="hl-identifier">__get_bottom</span><span class="hl-brackets">)

	</span><span class="hl-reserved">def </span><span class="hl-identifier">__init__</span><span class="hl-brackets">(</span><span class="hl-identifier">self</span><span class="hl-code">, </span><span class="hl-identifier">image_file</span><span class="hl-code">, </span><span class="hl-identifier">image_data</span><span class="hl-code">=</span><span class="hl-reserved">None</span><span class="hl-code">, **</span><span class="hl-identifier">kwargs</span><span class="hl-brackets">)</span><span class="hl-default">:

		</span><span class="hl-comment">#init standard variables
		</span><span class="hl-identifier">self</span><span class="hl-default">.</span><span class="hl-identifier">image_file</span><span class="hl-default"> = </span><span class="hl-identifier">image_file
		if </span><span class="hl-brackets">(</span><span class="hl-identifier">image_data </span><span class="hl-reserved">is None</span><span class="hl-brackets">)</span><span class="hl-default">:
			</span><span class="hl-identifier">self</span><span class="hl-default">.</span><span class="hl-identifier">image</span><span class="hl-default"> = </span><span class="hl-identifier">helper</span><span class="hl-default">.</span><span class="hl-identifier">load_image</span><span class="hl-brackets">(</span><span class="hl-identifier">image_file</span><span class="hl-brackets">)
		</span><span class="hl-reserved">else</span><span class="hl-default">:
			</span><span class="hl-identifier">self</span><span class="hl-default">.</span><span class="hl-identifier">image</span><span class="hl-default"> = </span><span class="hl-identifier">image_data
		self</span><span class="hl-default">.</span><span class="hl-identifier">x</span><span class="hl-default"> = </span><span class="hl-number">0
		</span><span class="hl-identifier">self</span><span class="hl-default">.</span><span class="hl-identifier">y</span><span class="hl-default"> = </span><span class="hl-number">0
		</span><span class="hl-identifier">self</span><span class="hl-default">.</span><span class="hl-identifier">dead</span><span class="hl-default"> = </span><span class="hl-reserved">False
		</span><span class="hl-comment">#Update the dict if they sent in any keywords
		</span><span class="hl-identifier">self</span><span class="hl-default">.</span><span class="hl-identifier">__dict__</span><span class="hl-default">.</span><span class="hl-identifier">update</span><span class="hl-brackets">(</span><span class="hl-identifier">kwargs</span><span class="hl-brackets">)

	</span><span class="hl-reserved">def </span><span class="hl-identifier">draw</span><span class="hl-brackets">(</span><span class="hl-identifier">self</span><span class="hl-brackets">)</span><span class="hl-default">:
		</span><span class="hl-identifier">self</span><span class="hl-default">.</span><span class="hl-identifier">image</span><span class="hl-default">.</span><span class="hl-identifier">blit</span><span class="hl-brackets">(</span><span class="hl-identifier">self</span><span class="hl-code">.</span><span class="hl-identifier">x</span><span class="hl-code">, </span><span class="hl-identifier">self</span><span class="hl-code">.</span><span class="hl-identifier">y</span><span class="hl-brackets">)

	</span><span class="hl-reserved">def </span><span class="hl-identifier">update</span><span class="hl-brackets">(</span><span class="hl-identifier">self</span><span class="hl-brackets">)</span><span class="hl-default">:
		</span><span class="hl-reserved">pass

	def </span><span class="hl-identifier">intersect</span><span class="hl-brackets">(</span><span class="hl-identifier">self</span><span class="hl-code">, </span><span class="hl-identifier">sprite</span><span class="hl-brackets">)</span><span class="hl-default">:
		</span><span class="hl-quotes">&quot;&quot;&quot;</span><span class="hl-string">Do the two sprites intersect?
		@param sprite - Sprite - The Sprite to test
		</span><span class="hl-quotes">&quot;&quot;&quot;
		</span><span class="hl-reserved">return </span><span class="hl-identifier">not </span><span class="hl-brackets">((</span><span class="hl-identifier">self</span><span class="hl-code">.</span><span class="hl-identifier">left</span><span class="hl-code"> &gt; </span><span class="hl-identifier">sprite</span><span class="hl-code">.</span><span class="hl-identifier">right</span><span class="hl-brackets">)
			</span><span class="hl-identifier">or </span><span class="hl-brackets">(</span><span class="hl-identifier">self</span><span class="hl-code">.</span><span class="hl-identifier">right</span><span class="hl-code"> &lt; </span><span class="hl-identifier">sprite</span><span class="hl-code">.</span><span class="hl-identifier">left</span><span class="hl-brackets">)
			</span><span class="hl-identifier">or </span><span class="hl-brackets">(</span><span class="hl-identifier">self</span><span class="hl-code">.</span><span class="hl-identifier">top</span><span class="hl-code"> &lt; </span><span class="hl-identifier">sprite</span><span class="hl-code">.</span><span class="hl-identifier">bottom</span><span class="hl-brackets">)
			</span><span class="hl-identifier">or </span><span class="hl-brackets">(</span><span class="hl-identifier">self</span><span class="hl-code">.</span><span class="hl-identifier">bottom</span><span class="hl-code"> &gt; </span><span class="hl-identifier">sprite</span><span class="hl-code">.</span><span class="hl-identifier">top</span><span class="hl-brackets">))

	</span><span class="hl-reserved">def </span><span class="hl-identifier">collide</span><span class="hl-brackets">(</span><span class="hl-identifier">self</span><span class="hl-code">, </span><span class="hl-identifier">sprite_list</span><span class="hl-brackets">)</span><span class="hl-default">:
		</span><span class="hl-quotes">&quot;&quot;&quot;</span><span class="hl-string">Determing ther are collisions with this
		sprite and the list of sprites
		@param sprite_list - A list of sprites
		@returns list - List of collisions</span><span class="hl-quotes">&quot;&quot;&quot;

		</span><span class="hl-identifier">lst_return</span><span class="hl-default"> = </span><span class="hl-brackets">[]
		</span><span class="hl-reserved">for </span><span class="hl-identifier">sprite </span><span class="hl-reserved">in </span><span class="hl-identifier">sprite_list</span><span class="hl-default">:
			</span><span class="hl-identifier">if </span><span class="hl-brackets">(</span><span class="hl-identifier">self</span><span class="hl-code">.</span><span class="hl-identifier">intersect</span><span class="hl-brackets">(</span><span class="hl-identifier">sprite</span><span class="hl-brackets">))</span><span class="hl-default">:
				</span><span class="hl-identifier">lst_return</span><span class="hl-default">.</span><span class="hl-identifier">append</span><span class="hl-brackets">(</span><span class="hl-identifier">sprite</span><span class="hl-brackets">)
		</span><span class="hl-reserved">return </span><span class="hl-identifier">lst_return

	</span><span class="hl-reserved">def </span><span class="hl-identifier">collide_once</span><span class="hl-brackets">(</span><span class="hl-identifier">self</span><span class="hl-code">, </span><span class="hl-identifier">sprite_list</span><span class="hl-brackets">)</span><span class="hl-default">:
		</span><span class="hl-quotes">&quot;&quot;&quot;</span><span class="hl-string">Determine if there is at least one
		collision between this sprite and the list
		@param sprite_list - A list of sprites
		@returns - None - No Collision, or the first
		sprite to collide
		</span><span class="hl-quotes">&quot;&quot;&quot;
		</span><span class="hl-reserved">for </span><span class="hl-identifier">sprite </span><span class="hl-reserved">in </span><span class="hl-identifier">sprite_list</span><span class="hl-default">:
			</span><span class="hl-identifier">if </span><span class="hl-brackets">(</span><span class="hl-identifier">self</span><span class="hl-code">.</span><span class="hl-identifier">intersect</span><span class="hl-brackets">(</span><span class="hl-identifier">sprite</span><span class="hl-brackets">))</span><span class="hl-default">:
				</span><span class="hl-reserved">return </span><span class="hl-identifier">sprite
		</span><span class="hl-reserved">return None</span></pre></div></div>
<p>So it may look complicated but it&#8217;s really not that difficult.  First off you will see that I create some positioning properties, left, right, top, and bottom. I do this so that the collision code is easier to read, plus it separates the positioning information from the implementation, in this case the <a href="http://pyglet.org/doc/api/pyglet.image.AbstractImage-class.html">pyglet.image.AbstractImage</a> member. If, in the future we were to add a rectangle class to the Sprite we don&#8217;t have to change a the code that interacts with the positioning, just what the position properties interact with.</p>
<p>You will also notice that in the Sprite class can either be initialized using an image file or the actual image data, which is a <a href="http://pyglet.org/doc/api/pyglet.image.AbstractImage-class.html">pyglet.image.AbstractImage</a>. The reason for this is instead of having to load the same image from the hard drive time and time again, and to avoid having the same image duplicated in memory in countless locations, we let the user decide which makes more sense.</p>
<p>Other then that it&#8217;s pretty simple stuff, some positioning information, and whether or not the sprite is Alive. If a sprite is dead it will be removed from the window.  There is also a draw method where the sprites image is blited to the window, and an update function where (if necessary) the sprite should update itself (position, image, etc).</p>
<p>Next we have a few collision functions that will help us to determine when out sprites collide. Now that we have the sprite class we need to add three more classes based off of the Sprite class. A SpaceShip class, a Bullet class which will be fired by the SpaceShip, and a Monster class.</p>
<p><img style="margin: 0pt 10px 10px 0pt;" src="http://www.learningpython.com/images/pyglet_01/ship.png" alt="Python Game PyGlet" border="0"/><br />
<img /></p>
<div class="hl-surround" ><div class="hl-main"><pre><span class="hl-reserved">class </span><span class="hl-identifier">SpaceShip</span><span class="hl-brackets">(</span><span class="hl-identifier">Sprite</span><span class="hl-brackets">)</span><span class="hl-default">:

	</span><span class="hl-reserved">def </span><span class="hl-identifier">__init__</span><span class="hl-brackets">(</span><span class="hl-identifier">self</span><span class="hl-code">, </span><span class="hl-identifier">text_x</span><span class="hl-code">, </span><span class="hl-identifier">text_y</span><span class="hl-code">, **</span><span class="hl-identifier">kwargs</span><span class="hl-brackets">)</span><span class="hl-default">:

		</span><span class="hl-identifier">self</span><span class="hl-default">.</span><span class="hl-identifier">kills</span><span class="hl-default"> = </span><span class="hl-number">0
		</span><span class="hl-identifier">Sprite</span><span class="hl-default">.</span><span class="hl-identifier">__init__</span><span class="hl-brackets">(</span><span class="hl-identifier">self</span><span class="hl-code">, </span><span class="hl-quotes">&quot;</span><span class="hl-string">ship.png</span><span class="hl-quotes">&quot;</span><span class="hl-code">, **</span><span class="hl-identifier">kwargs</span><span class="hl-brackets">)

		</span><span class="hl-comment">#Create a font for kill message
		</span><span class="hl-identifier">self</span><span class="hl-default">.</span><span class="hl-identifier">font</span><span class="hl-default"> = </span><span class="hl-identifier">font</span><span class="hl-default">.</span><span class="hl-identifier">load</span><span class="hl-brackets">(</span><span class="hl-quotes">'</span><span class="hl-string">Arial</span><span class="hl-quotes">'</span><span class="hl-code">, </span><span class="hl-number">28</span><span class="hl-brackets">)
		</span><span class="hl-comment">#The pyglet.font.Text object to display the FPS
		</span><span class="hl-identifier">self</span><span class="hl-default">.</span><span class="hl-identifier">kill_text</span><span class="hl-default"> = </span><span class="hl-identifier">font</span><span class="hl-default">.</span><span class="hl-identifier">Text</span><span class="hl-brackets">(</span><span class="hl-identifier">self</span><span class="hl-code">.</span><span class="hl-identifier">font</span><span class="hl-code">, </span><span class="hl-identifier">y</span><span class="hl-code">=</span><span class="hl-identifier">text_y</span><span class="hl-code">, </span><span class="hl-identifier">x</span><span class="hl-code">=</span><span class="hl-identifier">text_x</span><span class="hl-brackets">)

	</span><span class="hl-reserved">def </span><span class="hl-identifier">draw</span><span class="hl-brackets">(</span><span class="hl-identifier">self</span><span class="hl-brackets">)</span><span class="hl-default">:
		</span><span class="hl-identifier">Sprite</span><span class="hl-default">.</span><span class="hl-identifier">draw</span><span class="hl-brackets">(</span><span class="hl-identifier">self</span><span class="hl-brackets">)
		</span><span class="hl-identifier">self</span><span class="hl-default">.</span><span class="hl-identifier">kill_text</span><span class="hl-default">.</span><span class="hl-identifier">text</span><span class="hl-default"> = </span><span class="hl-brackets">(</span><span class="hl-quotes">&quot;</span><span class="hl-string">Kills: %d</span><span class="hl-quotes">&quot;</span><span class="hl-brackets">)</span><span class="hl-default"> % </span><span class="hl-brackets">(</span><span class="hl-identifier">self</span><span class="hl-code">.</span><span class="hl-identifier">kills</span><span class="hl-brackets">)
		</span><span class="hl-identifier">self</span><span class="hl-default">.</span><span class="hl-identifier">kill_text</span><span class="hl-default">.</span><span class="hl-identifier">draw</span><span class="hl-brackets">()

	</span><span class="hl-reserved">def </span><span class="hl-identifier">on_kill</span><span class="hl-brackets">(</span><span class="hl-identifier">self</span><span class="hl-brackets">)</span><span class="hl-default">:
		</span><span class="hl-identifier">self</span><span class="hl-default">.</span><span class="hl-identifier">kills</span><span class="hl-default"> += </span><span class="hl-number">1</span></pre></div></div>
<p>The SpaceShip class doesn&#8217;t do that much above and beyond the base class. It has a data member &#8220;kills&#8221; that keeps track of the number of monsters that it kills, and a <a href="http://pyglet.org/doc/api/pyglet.font.Text-class.html">pyglet.font.Text</a> member that will display the number of kills on the screen. The position of the &#8220;kill text&#8221; is also passed into the SpaceShip constructor.</p>
<p><img style="margin: 0pt 10px 10px 0pt;" src="http://www.learningpython.com/images/pyglet_01/bullet.png" alt="Python Game PyGlet" border="0"/><br />
<img /></p>
<div class="hl-surround" ><div class="hl-main"><pre><span class="hl-reserved">class </span><span class="hl-identifier">Bullet</span><span class="hl-brackets">(</span><span class="hl-identifier">Sprite</span><span class="hl-brackets">)</span><span class="hl-default">:

	</span><span class="hl-reserved">def </span><span class="hl-identifier">__init__</span><span class="hl-brackets">(</span><span class="hl-identifier">self</span><span class="hl-code">, </span><span class="hl-identifier">parent_ship</span><span class="hl-code">, </span><span class="hl-identifier">image_data</span><span class="hl-code">, </span><span class="hl-identifier">top</span><span class="hl-code">, **</span><span class="hl-identifier">kwargs</span><span class="hl-brackets">)</span><span class="hl-default">:
		</span><span class="hl-identifier">self</span><span class="hl-default">.</span><span class="hl-identifier">velocity</span><span class="hl-default"> = </span><span class="hl-number">5
		</span><span class="hl-identifier">self</span><span class="hl-default">.</span><span class="hl-identifier">screen_top</span><span class="hl-default"> = </span><span class="hl-identifier">top
		self</span><span class="hl-default">.</span><span class="hl-identifier">parent_ship</span><span class="hl-default"> = </span><span class="hl-identifier">parent_ship
		Sprite</span><span class="hl-default">.</span><span class="hl-identifier">__init__</span><span class="hl-brackets">(</span><span class="hl-identifier">self</span><span class="hl-code">,</span><span class="hl-quotes">&quot;&quot;</span><span class="hl-code">, </span><span class="hl-identifier">image_data</span><span class="hl-code">, **</span><span class="hl-identifier">kwargs</span><span class="hl-brackets">)

	</span><span class="hl-reserved">def </span><span class="hl-identifier">update</span><span class="hl-brackets">(</span><span class="hl-identifier">self</span><span class="hl-brackets">)</span><span class="hl-default">:
		</span><span class="hl-identifier">self</span><span class="hl-default">.</span><span class="hl-identifier">y</span><span class="hl-default"> += </span><span class="hl-identifier">self</span><span class="hl-default">.</span><span class="hl-identifier">velocity
		</span><span class="hl-comment">#Have we gone off the screen?
		</span><span class="hl-identifier">if </span><span class="hl-brackets">(</span><span class="hl-identifier">self</span><span class="hl-code">.</span><span class="hl-identifier">bottom</span><span class="hl-code"> &gt; </span><span class="hl-identifier">self</span><span class="hl-code">.</span><span class="hl-identifier">screen_top</span><span class="hl-brackets">)</span><span class="hl-default">:
			</span><span class="hl-identifier">self</span><span class="hl-default">.</span><span class="hl-identifier">dead</span><span class="hl-default"> = </span><span class="hl-reserved">True

	def </span><span class="hl-identifier">on_kill</span><span class="hl-brackets">(</span><span class="hl-identifier">self</span><span class="hl-brackets">)</span><span class="hl-default">:
		</span><span class="hl-quotes">&quot;&quot;&quot;</span><span class="hl-string">We have hit a monster let the parent know</span><span class="hl-quotes">&quot;&quot;&quot;
		</span><span class="hl-identifier">self</span><span class="hl-default">.</span><span class="hl-identifier">parent_ship</span><span class="hl-default">.</span><span class="hl-identifier">on_kill</span><span class="hl-brackets">()</span></pre></div></div>
<p>The Bullet class will represent bullets fired by the SpaceShip class, so it adds three new data members the:</p>
<p>1) The velocity &#8211; which controls how fast the bullet moves.<br />
2) The screen_top &#8211; Which represents the top of the screen is and will be used to destroy the bullet when the bullet moves past the top of the screen.<br />
3) The parent_ship &#8211; This is the SpaceShip that fired the bullet. This will be used to let the ship know when it has made a kill.</p>
<p>The final sprite is the Monster sprite:</p>
<p><img style="margin: 0pt 10px 10px 0pt;" src="http://www.learningpython.com/images/pyglet_01/monster.png" alt="Python Game PyGlet" border="0"/><br />
<img /></p>
<div class="hl-surround" style="height:280px;"><div class="hl-main"><pre><span class="hl-reserved">class </span><span class="hl-identifier">Monster</span><span class="hl-brackets">(</span><span class="hl-identifier">Sprite</span><span class="hl-brackets">)</span><span class="hl-default">:

	</span><span class="hl-reserved">def </span><span class="hl-identifier">__init__</span><span class="hl-brackets">(</span><span class="hl-identifier">self</span><span class="hl-code">, </span><span class="hl-identifier">image_data</span><span class="hl-code">, **</span><span class="hl-identifier">kwargs</span><span class="hl-brackets">)</span><span class="hl-default">:
		</span><span class="hl-identifier">self</span><span class="hl-default">.</span><span class="hl-identifier">y_velocity</span><span class="hl-default"> = </span><span class="hl-number">5
		</span><span class="hl-identifier">self</span><span class="hl-default">.</span><span class="hl-identifier">set_x_velocity</span><span class="hl-brackets">()
		</span><span class="hl-identifier">self</span><span class="hl-default">.</span><span class="hl-identifier">x_move_count</span><span class="hl-default"> = </span><span class="hl-number">0
		</span><span class="hl-identifier">self</span><span class="hl-default">.</span><span class="hl-identifier">x_velocity
		Sprite</span><span class="hl-default">.</span><span class="hl-identifier">__init__</span><span class="hl-brackets">(</span><span class="hl-identifier">self</span><span class="hl-code">, </span><span class="hl-quotes">&quot;&quot;</span><span class="hl-code">, </span><span class="hl-identifier">image_data</span><span class="hl-code">, **</span><span class="hl-identifier">kwargs</span><span class="hl-brackets">)

	</span><span class="hl-reserved">def </span><span class="hl-identifier">update</span><span class="hl-brackets">(</span><span class="hl-identifier">self</span><span class="hl-brackets">)</span><span class="hl-default">:
		</span><span class="hl-identifier">self</span><span class="hl-default">.</span><span class="hl-identifier">y</span><span class="hl-default"> -= </span><span class="hl-identifier">self</span><span class="hl-default">.</span><span class="hl-identifier">y_velocity
		self</span><span class="hl-default">.</span><span class="hl-identifier">x</span><span class="hl-default"> += </span><span class="hl-identifier">self</span><span class="hl-default">.</span><span class="hl-identifier">x_velocity</span><span class="hl-comment">#random.randint(-3,3)
		</span><span class="hl-identifier">self</span><span class="hl-default">.</span><span class="hl-identifier">x_move_count</span><span class="hl-default"> += </span><span class="hl-number">1
		</span><span class="hl-comment">#Have we gone beneath the botton of the screen?
		</span><span class="hl-identifier">if </span><span class="hl-brackets">(</span><span class="hl-identifier">self</span><span class="hl-code">.</span><span class="hl-identifier">y</span><span class="hl-code"> &lt; </span><span class="hl-number">0</span><span class="hl-brackets">)</span><span class="hl-default">:
			</span><span class="hl-identifier">self</span><span class="hl-default">.</span><span class="hl-identifier">dead</span><span class="hl-default"> = </span><span class="hl-reserved">True

		</span><span class="hl-identifier">if </span><span class="hl-brackets">(</span><span class="hl-identifier">self</span><span class="hl-code">.</span><span class="hl-identifier">x_move_count</span><span class="hl-code"> &gt;=</span><span class="hl-number">30</span><span class="hl-brackets">)</span><span class="hl-default">:
			</span><span class="hl-identifier">self</span><span class="hl-default">.</span><span class="hl-identifier">x_move_count</span><span class="hl-default"> = </span><span class="hl-number">0
			</span><span class="hl-identifier">self</span><span class="hl-default">.</span><span class="hl-identifier">set_x_velocity</span><span class="hl-brackets">()

	</span><span class="hl-reserved">def </span><span class="hl-identifier">set_x_velocity</span><span class="hl-brackets">(</span><span class="hl-identifier">self</span><span class="hl-brackets">)</span><span class="hl-default">:
		</span><span class="hl-identifier">self</span><span class="hl-default">.</span><span class="hl-identifier">x_velocity</span><span class="hl-default"> = </span><span class="hl-identifier">random</span><span class="hl-default">.</span><span class="hl-identifier">randint</span><span class="hl-brackets">(</span><span class="hl-code">-</span><span class="hl-number">3</span><span class="hl-code">,</span><span class="hl-number">3</span><span class="hl-brackets">)</span></pre></div></div>
<p>The Monster sprite will be moving from the top of the screen to the bottom of the screen, which is the opposite of the Bullet and is controlled by the y_velocity data member. But unlike the bullet the Monster sprite will also have some horizontal motion built it, which is controlled by the x_velocity data member, and set in the set_x_velocity() function. What is interesting about the x_velocity is that there is a bit of randomness built into it, it will be a random number from -3 in the left direct to 3 in the right direction. It will also change every thirty updates, giving the Monster a lazy side to side motion making it a bit more difficult for the SpaceShip to shoot it.</p>
<p>The Monster sprite does not have a bottom data member to tell it when it has moved off of the screen. The reason for this is that since the Monster will be moving down from the top of the screen, and we will can tell if it&#8217;s off the screen when it&#8217;s y, or top, data members are less then zero.</p>
<h2>Adding the Sprites to the Game</h2>
<p>Now that we have our sprite classes we need to use them in the main SpaceGameWindow class. There are a few ways to do this, but what I ended up doing was creating three new data members: &#8216;bullets&#8217; and &#8216;monsters&#8217;, both lists of sprites, and &#8217;ship&#8217; which will be the one and only ShapShip sprite.</p>
<p>The Sprites and some other data is initialized in the init_sprites() function:</p>
<div class="hl-surround" ><div class="hl-main"><pre><span class="hl-reserved">def </span><span class="hl-identifier">init_sprites</span><span class="hl-brackets">(</span><span class="hl-identifier">self</span><span class="hl-brackets">)</span><span class="hl-default">:
	</span><span class="hl-identifier">self</span><span class="hl-default">.</span><span class="hl-identifier">bullets</span><span class="hl-default"> = </span><span class="hl-brackets">[]
	</span><span class="hl-identifier">self</span><span class="hl-default">.</span><span class="hl-identifier">monsters</span><span class="hl-default"> = </span><span class="hl-brackets">[]
	</span><span class="hl-identifier">self</span><span class="hl-default">.</span><span class="hl-identifier">ship</span><span class="hl-default"> = </span><span class="hl-identifier">SpaceShip</span><span class="hl-brackets">(</span><span class="hl-identifier">self</span><span class="hl-code">.</span><span class="hl-identifier">width</span><span class="hl-code"> - </span><span class="hl-number">150</span><span class="hl-code">, </span><span class="hl-number">10</span><span class="hl-code">, </span><span class="hl-identifier">x</span><span class="hl-code">=</span><span class="hl-number">100</span><span class="hl-code">,</span><span class="hl-identifier">y</span><span class="hl-code">=</span><span class="hl-number">100</span><span class="hl-brackets">)
	</span><span class="hl-identifier">self</span><span class="hl-default">.</span><span class="hl-identifier">bullet_image</span><span class="hl-default"> = </span><span class="hl-identifier">helper</span><span class="hl-default">.</span><span class="hl-identifier">load_image</span><span class="hl-brackets">(</span><span class="hl-quotes">&quot;</span><span class="hl-string">bullet.png</span><span class="hl-quotes">&quot;</span><span class="hl-brackets">)
	</span><span class="hl-identifier">self</span><span class="hl-default">.</span><span class="hl-identifier">monster_image</span><span class="hl-default"> = </span><span class="hl-identifier">helper</span><span class="hl-default">.</span><span class="hl-identifier">load_image</span><span class="hl-brackets">(</span><span class="hl-quotes">&quot;</span><span class="hl-string">monster.png</span><span class="hl-quotes">&quot;</span><span class="hl-brackets">)</span></pre></div></div>
<p>All we do is create the two lists to store our sprites, the SpaceShip sprites, and use our helper to load the images that we will use for the Bullet and Monster sprites.</p>
<p>The next step is to change the draw loop so that we actually draw our sprites. There are a few more changes to be made in the main_loop() function but overall it remains pretty simple:</p>
<div class="hl-surround" style="height:280px;"><div class="hl-main"><pre><span class="hl-reserved">def </span><span class="hl-identifier">main_loop</span><span class="hl-brackets">(</span><span class="hl-identifier">self</span><span class="hl-brackets">)</span><span class="hl-default">:

	</span><span class="hl-comment">#Create a font for our FPS clock
	</span><span class="hl-identifier">ft</span><span class="hl-default"> = </span><span class="hl-identifier">font</span><span class="hl-default">.</span><span class="hl-identifier">load</span><span class="hl-brackets">(</span><span class="hl-quotes">'</span><span class="hl-string">Arial</span><span class="hl-quotes">'</span><span class="hl-code">, </span><span class="hl-number">28</span><span class="hl-brackets">)
	</span><span class="hl-comment">#The pyglet.font.Text object to display the FPS
	</span><span class="hl-identifier">fps_text</span><span class="hl-default"> = </span><span class="hl-identifier">font</span><span class="hl-default">.</span><span class="hl-identifier">Text</span><span class="hl-brackets">(</span><span class="hl-identifier">ft</span><span class="hl-code">, </span><span class="hl-identifier">y</span><span class="hl-code">=</span><span class="hl-number">10</span><span class="hl-brackets">)

	</span><span class="hl-comment">#Schedule the Monster creation
	</span><span class="hl-identifier">clock</span><span class="hl-default">.</span><span class="hl-identifier">schedule_interval</span><span class="hl-brackets">(</span><span class="hl-identifier">self</span><span class="hl-code">.</span><span class="hl-identifier">create_monster</span><span class="hl-code">, </span><span class="hl-number">0.3</span><span class="hl-brackets">)
	</span><span class="hl-identifier">clock</span><span class="hl-default">.</span><span class="hl-identifier">set_fps_limit</span><span class="hl-brackets">(</span><span class="hl-number">30</span><span class="hl-brackets">)

	</span><span class="hl-reserved">while not </span><span class="hl-identifier">self</span><span class="hl-default">.</span><span class="hl-identifier">has_exit</span><span class="hl-default">:
		</span><span class="hl-identifier">self</span><span class="hl-default">.</span><span class="hl-identifier">dispatch_events</span><span class="hl-brackets">()
		</span><span class="hl-identifier">self</span><span class="hl-default">.</span><span class="hl-identifier">clear</span><span class="hl-brackets">()

		</span><span class="hl-identifier">self</span><span class="hl-default">.</span><span class="hl-identifier">update</span><span class="hl-brackets">()
		</span><span class="hl-identifier">self</span><span class="hl-default">.</span><span class="hl-identifier">draw</span><span class="hl-brackets">()

		</span><span class="hl-comment">#Tick the clock
		</span><span class="hl-identifier">clock</span><span class="hl-default">.</span><span class="hl-identifier">tick</span><span class="hl-brackets">()
		</span><span class="hl-comment">#Gets fps and draw it
		</span><span class="hl-identifier">fps_text</span><span class="hl-default">.</span><span class="hl-identifier">text</span><span class="hl-default"> = </span><span class="hl-brackets">(</span><span class="hl-quotes">&quot;</span><span class="hl-string">fps: %d</span><span class="hl-quotes">&quot;</span><span class="hl-brackets">)</span><span class="hl-default"> % </span><span class="hl-brackets">(</span><span class="hl-identifier">clock</span><span class="hl-code">.</span><span class="hl-identifier">get_fps</span><span class="hl-brackets">())
		</span><span class="hl-identifier">fps_text</span><span class="hl-default">.</span><span class="hl-identifier">draw</span><span class="hl-brackets">()
		</span><span class="hl-identifier">self</span><span class="hl-default">.</span><span class="hl-identifier">flip</span><span class="hl-brackets">()</span></pre></div></div>
<p>There is quite a bit happening here so I&#8217;ll take a little bit of time to explain everything that is new. One of the things that I want to happen is to have monsters created after a certain amount of time has passed. To to this I use the <a href="http://www.pyglet.org/doc/api/pyglet.clock-module.html#schedule_interval">clock.schedule_interval</a> function.</p>
<div class="hl-surround" ><div class="hl-main"><pre><span class="hl-comment">#Schedule the Monster creation
</span><span class="hl-identifier">clock</span><span class="hl-default">.</span><span class="hl-identifier">schedule_interval</span><span class="hl-brackets">(</span><span class="hl-identifier">self</span><span class="hl-code">.</span><span class="hl-identifier">create_monster</span><span class="hl-code">, </span><span class="hl-number">0.3</span><span class="hl-brackets">)</span></pre></div></div>
<p>What this will do is call the create_monster() function every 0.3 seconds. The create_monster() function is pretty simple, it simply creates a Monster sprite in a random location provided that there is less then the maximum amount of Monsters currently around:</p>
<p><code><br />
def create_monster(self, interval):<br />
	if (len(self.monsters) &lt; self.max_monsters):<br />
		self.monsters.append(Monster(self.monster_image<br />
			, x=random.randint(0, self.width) , y=self.height))<br />
</code></p>
<p>max_monsters is defined in the __int__() function to be 30. The next new feature is the limiting of the frame rate. For such a simple game I limit it to 30 frames per second using the <a href="http://www.pyglet.org/doc/api/pyglet.clock-module.html#set_fps_limit">set_fps_limit </a>  function.</p>
<p>Other then that there are only two new calls in the main main loop and that is:</p>
<div class="hl-surround" ><div class="hl-main"><pre><span class="hl-identifier">self</span><span class="hl-default">.</span><span class="hl-identifier">update</span><span class="hl-brackets">()
</span><span class="hl-identifier">self</span><span class="hl-default">.</span><span class="hl-identifier">draw</span><span class="hl-brackets">()</span></pre></div></div>
<p>update() is basically a function that is used to update everything that is happening on the screen: sprite positions, scores whatever you want. Then the draw() function is basically the function where everything that needs to be drawn onto the screen gets drawn.</p>
<div class="hl-surround" style="height:280px;"><div class="hl-main"><pre><span class="hl-reserved">def </span><span class="hl-identifier">update</span><span class="hl-brackets">(</span><span class="hl-identifier">self</span><span class="hl-brackets">)</span><span class="hl-default">:

	</span><span class="hl-identifier">to_remove</span><span class="hl-default"> = </span><span class="hl-brackets">[]
	</span><span class="hl-reserved">for </span><span class="hl-identifier">sprite </span><span class="hl-reserved">in </span><span class="hl-identifier">self</span><span class="hl-default">.</span><span class="hl-identifier">monsters</span><span class="hl-default">:
		</span><span class="hl-identifier">sprite</span><span class="hl-default">.</span><span class="hl-identifier">update</span><span class="hl-brackets">()
		</span><span class="hl-comment">#Is it dead?
		</span><span class="hl-identifier">if </span><span class="hl-brackets">(</span><span class="hl-identifier">sprite</span><span class="hl-code">.</span><span class="hl-identifier">dead</span><span class="hl-brackets">)</span><span class="hl-default">:
			</span><span class="hl-identifier">to_remove</span><span class="hl-default">.</span><span class="hl-identifier">append</span><span class="hl-brackets">(</span><span class="hl-identifier">sprite</span><span class="hl-brackets">)
	</span><span class="hl-comment">#Remove dead sprites
	</span><span class="hl-reserved">for </span><span class="hl-identifier">sprite </span><span class="hl-reserved">in </span><span class="hl-identifier">to_remove</span><span class="hl-default">:
		</span><span class="hl-identifier">self</span><span class="hl-default">.</span><span class="hl-identifier">monsters</span><span class="hl-default">.</span><span class="hl-identifier">remove</span><span class="hl-brackets">(</span><span class="hl-identifier">sprite</span><span class="hl-brackets">)

	</span><span class="hl-comment">#Bullet update and collision
	</span><span class="hl-identifier">to_remove</span><span class="hl-default"> = </span><span class="hl-brackets">[]
	</span><span class="hl-reserved">for </span><span class="hl-identifier">sprite </span><span class="hl-reserved">in </span><span class="hl-identifier">self</span><span class="hl-default">.</span><span class="hl-identifier">bullets</span><span class="hl-default">:
		</span><span class="hl-identifier">sprite</span><span class="hl-default">.</span><span class="hl-identifier">update</span><span class="hl-brackets">()
		</span><span class="hl-identifier">if </span><span class="hl-brackets">(</span><span class="hl-reserved">not </span><span class="hl-identifier">sprite</span><span class="hl-code">.</span><span class="hl-identifier">dead</span><span class="hl-brackets">)</span><span class="hl-default">:
			</span><span class="hl-identifier">monster_hit</span><span class="hl-default"> = </span><span class="hl-identifier">sprite</span><span class="hl-default">.</span><span class="hl-identifier">collide_once</span><span class="hl-brackets">(</span><span class="hl-identifier">self</span><span class="hl-code">.</span><span class="hl-identifier">monsters</span><span class="hl-brackets">)
			</span><span class="hl-identifier">if </span><span class="hl-brackets">(</span><span class="hl-identifier">monster_hit </span><span class="hl-reserved">is not None</span><span class="hl-brackets">)</span><span class="hl-default">:
				</span><span class="hl-identifier">sprite</span><span class="hl-default">.</span><span class="hl-identifier">on_kill</span><span class="hl-brackets">()
				</span><span class="hl-identifier">self</span><span class="hl-default">.</span><span class="hl-identifier">monsters</span><span class="hl-default">.</span><span class="hl-identifier">remove</span><span class="hl-brackets">(</span><span class="hl-identifier">monster_hit</span><span class="hl-brackets">)
				</span><span class="hl-identifier">to_remove</span><span class="hl-default">.</span><span class="hl-identifier">append</span><span class="hl-brackets">(</span><span class="hl-identifier">sprite</span><span class="hl-brackets">)
		</span><span class="hl-reserved">else</span><span class="hl-default">:
			</span><span class="hl-identifier">to_remove</span><span class="hl-default">.</span><span class="hl-identifier">append</span><span class="hl-brackets">(</span><span class="hl-identifier">sprite</span><span class="hl-brackets">)
	</span><span class="hl-comment">#Remove bullets that hit monsters
	</span><span class="hl-reserved">for </span><span class="hl-identifier">sprite </span><span class="hl-reserved">in </span><span class="hl-identifier">to_remove</span><span class="hl-default">:
		</span><span class="hl-identifier">self</span><span class="hl-default">.</span><span class="hl-identifier">bullets</span><span class="hl-default">.</span><span class="hl-identifier">remove</span><span class="hl-brackets">(</span><span class="hl-identifier">sprite</span><span class="hl-brackets">)

	</span><span class="hl-identifier">self</span><span class="hl-default">.</span><span class="hl-identifier">ship</span><span class="hl-default">.</span><span class="hl-identifier">update</span><span class="hl-brackets">()
	</span><span class="hl-comment">#Is it dead?
	</span><span class="hl-identifier">monster_hit</span><span class="hl-default"> = </span><span class="hl-identifier">self</span><span class="hl-default">.</span><span class="hl-identifier">ship</span><span class="hl-default">.</span><span class="hl-identifier">collide_once</span><span class="hl-brackets">(</span><span class="hl-identifier">self</span><span class="hl-code">.</span><span class="hl-identifier">monsters</span><span class="hl-brackets">)
	</span><span class="hl-identifier">if </span><span class="hl-brackets">(</span><span class="hl-identifier">monster_hit </span><span class="hl-reserved">is not None</span><span class="hl-brackets">)</span><span class="hl-default">:
		</span><span class="hl-identifier">self</span><span class="hl-default">.</span><span class="hl-identifier">ship</span><span class="hl-default">.</span><span class="hl-identifier">dead</span><span class="hl-default"> = </span><span class="hl-reserved">True
		</span><span class="hl-identifier">self</span><span class="hl-default">.</span><span class="hl-identifier">has_exit</span><span class="hl-default"> = </span><span class="hl-reserved">True</span></pre></div></div>
<p>I won&#8217;t explain this function too much since in general it&#8217;s pretty straight forward. We are basically updating all of the sprites, checking for collisions or them being &#8220;dead&#8221; and if the sprites need to be removed then we do. </p>
<p>The first step is to update all of the monsters. The second step is to update all of the Bullet sprites and if they are not dead (off the screen) check for a collision between them at the Monster sprites. If the Bullet hits a Monster sprite then it and the monster are both dead and will be removed. </p>
<p>Then we check to see if the SpaceShip sprite has collided with any of the Monster sprites. If it has we signal the end of the game by setting the <a href="http://www.pyglet.org/doc/api/pyglet.window.event.WindowExitHandler-class.html#has_exit">has_exit</a> window handler.</p>
<p>The draw function is very simple, we simply draw all of the sprites:</p>
<div class="hl-surround" ><div class="hl-main"><pre><span class="hl-reserved">def </span><span class="hl-identifier">draw</span><span class="hl-brackets">(</span><span class="hl-identifier">self</span><span class="hl-brackets">)</span><span class="hl-default">:

	</span><span class="hl-reserved">for </span><span class="hl-identifier">sprite </span><span class="hl-reserved">in </span><span class="hl-identifier">self</span><span class="hl-default">.</span><span class="hl-identifier">bullets</span><span class="hl-default">:
		</span><span class="hl-identifier">sprite</span><span class="hl-default">.</span><span class="hl-identifier">draw</span><span class="hl-brackets">()
	</span><span class="hl-reserved">for </span><span class="hl-identifier">sprite </span><span class="hl-reserved">in </span><span class="hl-identifier">self</span><span class="hl-default">.</span><span class="hl-identifier">monsters</span><span class="hl-default">:
		</span><span class="hl-identifier">sprite</span><span class="hl-default">.</span><span class="hl-identifier">draw</span><span class="hl-brackets">()
	</span><span class="hl-identifier">self</span><span class="hl-default">.</span><span class="hl-identifier">ship</span><span class="hl-default">.</span><span class="hl-identifier">draw</span><span class="hl-brackets">()</span></pre></div></div>
<h2>Events</h2>
<p>The next step to setup some event handling, which was the whole reason that we made our main class use <a href="http://pyglet.org/doc/api/pyglet.window.Window-class.html">pyglet.window.Window</a> as the base class way back before we got sidetracked on these sprites and game play.</p>
<p>Fortunately for us adding event handlers is very simple, we simply have to define one of the <a href="http://www.pyglet.org/doc/api/pyglet.window.Window-class.html#section-Events">event functions</a></p>
<p>Since we want to use mouse motion to move the space ship we need to catch the <a href="http://www.pyglet.org/doc/api/pyglet.window.Window-class.html#section-Events">mouse motion event</a>.</p>
<div class="hl-surround" ><div class="hl-main"><pre><span class="hl-reserved">def </span><span class="hl-identifier">on_mouse_motion</span><span class="hl-brackets">(</span><span class="hl-identifier">self</span><span class="hl-code">, </span><span class="hl-identifier">x</span><span class="hl-code">, </span><span class="hl-identifier">y</span><span class="hl-code">, </span><span class="hl-identifier">dx</span><span class="hl-code">, </span><span class="hl-identifier">dy</span><span class="hl-brackets">)</span><span class="hl-default">:
	</span><span class="hl-identifier">self</span><span class="hl-default">.</span><span class="hl-identifier">ship</span><span class="hl-default">.</span><span class="hl-identifier">x</span><span class="hl-default"> = </span><span class="hl-identifier">x
	self</span><span class="hl-default">.</span><span class="hl-identifier">ship</span><span class="hl-default">.</span><span class="hl-identifier">y</span><span class="hl-default"> = </span><span class="hl-identifier">y</span></pre></div></div>
<p>Pretty simple! We just need to add the function for the even and as long as we call <a href="http://www.pyglet.org/doc/api/pyglet.window.Window-class.html#dispatch_events">dispatch_events</a> our event will be handed.</p>
<p>We also want the spaceship to fire when we click the left mouse button. So to do that we need to handle the <a href="http://www.pyglet.org/doc/api/pyglet.window.Window-class.html#on_mouse_press">mouse press event</a>.</p>
<div class="hl-surround" ><div class="hl-main"><pre><span class="hl-reserved">def </span><span class="hl-identifier">on_mouse_press</span><span class="hl-brackets">(</span><span class="hl-identifier">self</span><span class="hl-code">, </span><span class="hl-identifier">x</span><span class="hl-code">, </span><span class="hl-identifier">y</span><span class="hl-code">, </span><span class="hl-identifier">button</span><span class="hl-code">, </span><span class="hl-identifier">modifiers</span><span class="hl-brackets">)</span><span class="hl-default">:

	</span><span class="hl-identifier">if </span><span class="hl-brackets">(</span><span class="hl-identifier">button</span><span class="hl-code"> == </span><span class="hl-number">1</span><span class="hl-brackets">)</span><span class="hl-default">:
		</span><span class="hl-identifier">self</span><span class="hl-default">.</span><span class="hl-identifier">bullets</span><span class="hl-default">.</span><span class="hl-identifier">append</span><span class="hl-brackets">(</span><span class="hl-identifier">Bullet</span><span class="hl-brackets">(</span><span class="hl-identifier">self</span><span class="hl-code">.</span><span class="hl-identifier">ship</span><span class="hl-code">
				, </span><span class="hl-identifier">self</span><span class="hl-code">.</span><span class="hl-identifier">bullet_image</span><span class="hl-code">
				, </span><span class="hl-identifier">self</span><span class="hl-code">.</span><span class="hl-identifier">height</span><span class="hl-code">
				, </span><span class="hl-identifier">x</span><span class="hl-code">=</span><span class="hl-identifier">x</span><span class="hl-code"> + </span><span class="hl-brackets">(</span><span class="hl-identifier">self</span><span class="hl-code">.</span><span class="hl-identifier">ship</span><span class="hl-code">.</span><span class="hl-identifier">image</span><span class="hl-code">.</span><span class="hl-identifier">width</span><span class="hl-code"> / </span><span class="hl-number">2</span><span class="hl-brackets">)</span><span class="hl-code"> - </span><span class="hl-brackets">(</span><span class="hl-identifier">self</span><span class="hl-code">.</span><span class="hl-identifier">bullet_image</span><span class="hl-code">.</span><span class="hl-identifier">width</span><span class="hl-code"> / </span><span class="hl-number">2</span><span class="hl-brackets">)</span><span class="hl-code">
				, </span><span class="hl-identifier">y</span><span class="hl-code">=</span><span class="hl-identifier">y</span><span class="hl-brackets">))</span></pre></div></div>
<p>Here we simply make sure that it was the left mouse button that was pressed, and it it was we create a bullet in the correct location using the correct image.</p>
<p>PyGlet does something interesting it gives you a mouse drag event, which is sent when a mouse button is down and the mouse is moved. During the &#8220;mouse drag&#8221; event the &#8220;mouse motion&#8221; event will not be sent. Sine the used will be clicking a lot we need to keep the Space Ship moving by handling the <a href="http://www.pyglet.org/doc/api/pyglet.window.Window-class.html#on_mouse_drag">mouse drag event</a>, if we don&#8217;t the ship will seem to pause if we move the mouse and click the left mouse button.</p>
<div class="hl-surround" ><div class="hl-main"><pre><span class="hl-reserved">def </span><span class="hl-identifier">on_mouse_drag</span><span class="hl-brackets">(</span><span class="hl-identifier">self</span><span class="hl-code">, </span><span class="hl-identifier">x</span><span class="hl-code">, </span><span class="hl-identifier">y</span><span class="hl-code">, </span><span class="hl-identifier">dx</span><span class="hl-code">, </span><span class="hl-identifier">dy</span><span class="hl-code">, </span><span class="hl-identifier">buttons</span><span class="hl-code">, </span><span class="hl-identifier">modifiers</span><span class="hl-brackets">)</span><span class="hl-default">:
	</span><span class="hl-identifier">self</span><span class="hl-default">.</span><span class="hl-identifier">ship</span><span class="hl-default">.</span><span class="hl-identifier">x</span><span class="hl-default"> = </span><span class="hl-identifier">x
	self</span><span class="hl-default">.</span><span class="hl-identifier">ship</span><span class="hl-default">.</span><span class="hl-identifier">y</span><span class="hl-default"> = </span><span class="hl-identifier">y</span></pre></div></div>
<p>This is exactly the same as the mouse motion handler, and in truth it could call on_mouse_motion() itself.</p>
<h2>Helper</h2>
<p>You might have noticed that I use a helper to load this images. This is pretty simple stuff located in a file called &#8220;helper.py&#8221; in the same directory as PyGletSpace.py:</p>
<div class="hl-surround" ><div class="hl-main"><pre><span class="hl-reserved">import </span><span class="hl-identifier">os
</span><span class="hl-reserved">from </span><span class="hl-identifier">pyglet </span><span class="hl-reserved">import </span><span class="hl-identifier">image

</span><span class="hl-reserved">def </span><span class="hl-identifier">get_image_dir</span><span class="hl-brackets">()</span><span class="hl-default">:
	</span><span class="hl-quotes">&quot;&quot;&quot;</span><span class="hl-string">Get the directory used to store the images
	@returns string - the directory
	</span><span class="hl-quotes">&quot;&quot;&quot;
	</span><span class="hl-identifier">directory</span><span class="hl-default"> = </span><span class="hl-identifier">os</span><span class="hl-default">.</span><span class="hl-identifier">path</span><span class="hl-default">.</span><span class="hl-identifier">abspath</span><span class="hl-brackets">(</span><span class="hl-identifier">os</span><span class="hl-code">.</span><span class="hl-identifier">path</span><span class="hl-code">.</span><span class="hl-identifier">dirname</span><span class="hl-brackets">(</span><span class="hl-identifier">__file__</span><span class="hl-brackets">))
	</span><span class="hl-identifier">directory</span><span class="hl-default"> = </span><span class="hl-identifier">os</span><span class="hl-default">.</span><span class="hl-identifier">path</span><span class="hl-default">.</span><span class="hl-identifier">join</span><span class="hl-brackets">(</span><span class="hl-identifier">directory</span><span class="hl-code">, </span><span class="hl-quotes">'</span><span class="hl-string">data</span><span class="hl-quotes">'</span><span class="hl-brackets">)
	</span><span class="hl-reserved">return </span><span class="hl-identifier">directory

</span><span class="hl-reserved">def </span><span class="hl-identifier">load_image</span><span class="hl-brackets">(</span><span class="hl-identifier">image_file_name</span><span class="hl-brackets">)</span><span class="hl-default">:

	</span><span class="hl-identifier">full_path</span><span class="hl-default"> = </span><span class="hl-identifier">os</span><span class="hl-default">.</span><span class="hl-identifier">path</span><span class="hl-default">.</span><span class="hl-identifier">join</span><span class="hl-brackets">(</span><span class="hl-identifier">get_image_dir</span><span class="hl-brackets">()</span><span class="hl-code">, </span><span class="hl-identifier">image_file_name</span><span class="hl-brackets">)
	</span><span class="hl-reserved">return </span><span class="hl-identifier">image</span><span class="hl-default">.</span><span class="hl-identifier">load</span><span class="hl-brackets">(</span><span class="hl-identifier">full_path</span><span class="hl-brackets">)</span></pre></div></div>
<h2>Done!</h2>
<p><img style="margin: 0pt 10px 10px 0pt;" src="http://www.learningpython.com/images/pyglet_01/pyglet_02.png" alt="Python Game PyGlet" border="0"/><br />
<img /></p>
<p>You can download the full source to this tutorial <a href="http://www.learningpython.com/sources/pygletSpace.tar.gz">here</a>.</p>
<p>That&#8217;s it for this wonderfully short game and lengthy tutorial. What&#8217;s I&#8217;ve found is that PyGlet is an extremely interesting library that I will continue to keep an eye on. At a certain point I had heard that it was going to be including some Sprite classes and collision classes as well, but it seems as though this may be on the back burner for the initial release.</p>
<p>It will be interesting to see where this goes, what I would like to see would be a simple 2d (since that&#8217;s all I&#8217;m interested in fooling around with for the most part) engine built on top of PyGlet. A simple way to work with all of the different features that a 2d game needs. Hopefully something like that will come along at some point, heck maybe it&#8217;s already out there and I just don&#8217;t know about it yet. But if anyone is working on one, or interested in setting something like this up drop me a line.</p>
<p>[1] http://www.pyglet.org/</p>
<div style="float:right;margin:0px 0px 0px 0px;"><a href="http://www.google.com/reader/link?url=http://www.learningpython.com/2007/11/10/creating-a-game-with-pyglet-and-python/&title=Creating a game with PyGlet and Python&srcTitle=learning python&srcURL=http://www.learningpython.com"target="_blank" rel=""><img border="0" src="http://www.learningpython.com/wp-content/plugins/wp-google-buzz/icon/12.png" style="opacity:1;filter:alpha(opacity=100)" onmouseover="this.style.opacity=0.8;this.filters.alpha.opacity=70" onmouseout="this.style.opacity=1;this.filters.alpha.opacity=100"/> </a></div>]]></content:encoded>
			<wfw:commentRss>http://www.learningpython.com/2007/11/10/creating-a-game-with-pyglet-and-python/feed/</wfw:commentRss>
		<slash:comments>21</slash:comments>
		</item>
		<item>
		<title>Python 3000 Status Update from Guido</title>
		<link>http://www.learningpython.com/2007/07/05/python-3000-status-update-from-guido/</link>
		<comments>http://www.learningpython.com/2007/07/05/python-3000-status-update-from-guido/#comments</comments>
		<pubDate>Thu, 05 Jul 2007 16:01:24 +0000</pubDate>
		<dc:creator>selsine</dc:creator>
				<category><![CDATA[News]]></category>
		<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[python]]></category>

		<guid isPermaLink="false">http://www.learningpython.com/2007/07/05/python-3000-status-update-from-guido/</guid>
		<description><![CDATA[
			
				
			
		
I just stumbled on this and I thought I&#8217;d pass it onto my fellow python programmers, it&#8217;s a python 3000 status update from Guido van Rossum.
Personally I&#8217;m looking forward to Python 3.0, I don&#8217;t know if I&#8217;ll like the break in backwards compatibility but a lot of the changes seem great.
Making the print statement a [...]]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style="float: right; margin-left: 10px;">
			<a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fwww.learningpython.com%2F2007%2F07%2F05%2Fpython-3000-status-update-from-guido%2F"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fwww.learningpython.com%2F2007%2F07%2F05%2Fpython-3000-status-update-from-guido%2F&amp;style=normal" height="61" width="50" /><br />
			</a>
		</div>
<p>I just stumbled on this and I thought I&#8217;d pass it onto my fellow python programmers, it&#8217;s a <a href="http://www.artima.com/weblogs/viewpost.jsp?thread=208549">python 3000 status update</a> from Guido van Rossum.</p>
<p>Personally I&#8217;m looking forward to Python 3.0, I don&#8217;t know if I&#8217;ll like the break in backwards compatibility but a lot of the changes seem great.</p>
<p>Making the print statement a function is a good choice in my opinion. </p>
<p>So instead of:</p>
<div class="hl-surround" style="height:28px;"><div class="hl-main"><pre><span class="hl-reserved">print </span><span class="hl-quotes">&quot;</span><span class="hl-string">this is printing</span><span class="hl-quotes">&quot;</span></pre></div></div>
<p>We&#8217;ll be using:</p>
<div class="hl-surround" style="height:28px;"><div class="hl-main"><pre><span class="hl-identifier">print</span><span class="hl-brackets">(</span><span class="hl-quotes">&quot;</span><span class="hl-string">this is python 3.0</span><span class="hl-quotes">&quot;</span><span class="hl-brackets">)</span></pre></div></div>
<p>Also instead of % to format strings, there will be a format() function, which is so much clearer in my opinion.</p>
<p>There are many other changes (say goodbye to old-style classes) so give the link a read and let me know what you think!</p>
<div style="float:right;margin:0px 0px 0px 0px;"><a href="http://www.google.com/reader/link?url=http://www.learningpython.com/2007/07/05/python-3000-status-update-from-guido/&title=Python 3000 Status Update from Guido&srcTitle=learning python&srcURL=http://www.learningpython.com"target="_blank" rel=""><img border="0" src="http://www.learningpython.com/wp-content/plugins/wp-google-buzz/icon/12.png" style="opacity:1;filter:alpha(opacity=100)" onmouseover="this.style.opacity=0.8;this.filters.alpha.opacity=70" onmouseout="this.style.opacity=1;this.filters.alpha.opacity=100"/> </a></div>]]></content:encoded>
			<wfw:commentRss>http://www.learningpython.com/2007/07/05/python-3000-status-update-from-guido/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>New Comment Moderation</title>
		<link>http://www.learningpython.com/2007/05/04/new-comment-moderation/</link>
		<comments>http://www.learningpython.com/2007/05/04/new-comment-moderation/#comments</comments>
		<pubDate>Fri, 04 May 2007 14:13:42 +0000</pubDate>
		<dc:creator>selsine</dc:creator>
				<category><![CDATA[News]]></category>
		<category><![CDATA[PyGTK]]></category>
		<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[pygame]]></category>
		<category><![CDATA[python]]></category>

		<guid isPermaLink="false">http://www.learningpython.com/2007/05/04/new-comment-moderation/</guid>
		<description><![CDATA[
			
				
			
		
Hey everyone, I&#8217;ve been getting hit with a bunch of spam comments over the last few days so I&#8217;ve made it so that all comments must be moderated before they will appear.
Sorry about this, I don&#8217;t like this form of comment posting, but hopefully after a few days I will be able to switch it [...]]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style="float: right; margin-left: 10px;">
			<a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fwww.learningpython.com%2F2007%2F05%2F04%2Fnew-comment-moderation%2F"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fwww.learningpython.com%2F2007%2F05%2F04%2Fnew-comment-moderation%2F&amp;style=normal" height="61" width="50" /><br />
			</a>
		</div>
<p>Hey everyone, I&#8217;ve been getting hit with a bunch of spam comments over the last few days so I&#8217;ve made it so that all comments must be moderated before they will appear.</p>
<p>Sorry about this, I don&#8217;t like this form of comment posting, but hopefully after a few days I will be able to switch it back to normal.</p>
<p>And sorry about the lack of posts here, yes I am still alive, it&#8217;s just that real life has been working me pretty hard these last few weeks.</p>
<p>I&#8217;ve been playing around with my PyGTK app and a new PyGame engine that I am working on from the ground up.  Something that I can understand and that I can use.  I&#8217;ll post more information about it when there is more information&#8230;right now it does next to nothing!</p>
<div style="float:right;margin:0px 0px 0px 0px;"><a href="http://www.google.com/reader/link?url=http://www.learningpython.com/2007/05/04/new-comment-moderation/&title=New Comment Moderation&srcTitle=learning python&srcURL=http://www.learningpython.com"target="_blank" rel=""><img border="0" src="http://www.learningpython.com/wp-content/plugins/wp-google-buzz/icon/12.png" style="opacity:1;filter:alpha(opacity=100)" onmouseover="this.style.opacity=0.8;this.filters.alpha.opacity=70" onmouseout="this.style.opacity=1;this.filters.alpha.opacity=100"/> </a></div>]]></content:encoded>
			<wfw:commentRss>http://www.learningpython.com/2007/05/04/new-comment-moderation/feed/</wfw:commentRss>
		<slash:comments>10</slash:comments>
		</item>
		<item>
		<title>Welcome Back!</title>
		<link>http://www.learningpython.com/2006/01/07/welcome-back/</link>
		<comments>http://www.learningpython.com/2006/01/07/welcome-back/#comments</comments>
		<pubDate>Sat, 07 Jan 2006 20:45:53 +0000</pubDate>
		<dc:creator>selsine</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://www.learningpython.com/2006/01/07/welcome-back/</guid>
		<description><![CDATA[
			
				
			
		
Hello everyone!  This is just a short post to let you all know that I have returned from my holidays eager to start learning Python.  My holidays were busy and fun but now that they are done I feel rejuvenated in my quest to learn another programming language.
Also, just to let you know, [...]]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style="float: right; margin-left: 10px;">
			<a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fwww.learningpython.com%2F2006%2F01%2F07%2Fwelcome-back%2F"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fwww.learningpython.com%2F2006%2F01%2F07%2Fwelcome-back%2F&amp;style=normal" height="61" width="50" /><br />
			</a>
		</div>
<p>Hello everyone!  This is just a short post to let you all know that I have returned from my holidays eager to start learning <a href="http://www.python.org/">Python</a>.  My holidays were busy and fun but now that they are done I feel rejuvenated in my quest to learn another programming language.</p>
<p>Also, just to let you know, this site is still under construction and will be worked on and updated in the next few weeks.</p>
<div style="float:right;margin:0px 0px 0px 0px;"><a href="http://www.google.com/reader/link?url=http://www.learningpython.com/2006/01/07/welcome-back/&title=Welcome Back!&srcTitle=learning python&srcURL=http://www.learningpython.com"target="_blank" rel=""><img border="0" src="http://www.learningpython.com/wp-content/plugins/wp-google-buzz/icon/12.png" style="opacity:1;filter:alpha(opacity=100)" onmouseover="this.style.opacity=0.8;this.filters.alpha.opacity=70" onmouseout="this.style.opacity=1;this.filters.alpha.opacity=100"/> </a></div>]]></content:encoded>
			<wfw:commentRss>http://www.learningpython.com/2006/01/07/welcome-back/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
