<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet href="http://feeds.doughellmann.com/~d/styles/atom10full.xsl" type="text/xsl" media="screen"?><?xml-stylesheet href="http://feeds.doughellmann.com/~d/styles/itemcontent.css" type="text/css" media="screen"?><feed xmlns="http://www.w3.org/2005/Atom" xmlns:openSearch="http://a9.com/-/spec/opensearchrss/1.0/" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0"><id>tag:blogger.com,1999:blog-5440028356946346379</id><updated>2008-07-07T08:23:50.209-04:00</updated><title type="text">Doug Hellmann</title><link rel="alternate" type="text/html" href="http://blog.doughellmann.com/" /><link rel="next" type="application/atom+xml" href="http://www.blogger.com/feeds/5440028356946346379/posts/default?start-index=26&amp;max-results=25&amp;redirect=false" /><link rel="http://schemas.google.com/g/2005#feed" type="application/atom+xml" href="http://blog.doughellmann.com/feeds/posts/default" /><author><name>Doug Hellmann</name><uri>http://www.blogger.com/profile/01892352754222143463</uri><email>noreply@blogger.com</email></author><generator version="7.00" uri="http://www.blogger.com">Blogger</generator><openSearch:totalResults>230</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><link rel="license" type="text/html" href="http://creativecommons.org/licenses/by-sa/2.0/" /><logo>http://creativecommons.org/images/public/somerights20.gif</logo><link rel="self" href="http://feeds.doughellmann.com/DougHellmann" type="application/atom+xml" /><entry><id>tag:blogger.com,1999:blog-5440028356946346379.post-6534219774437987729</id><published>2008-07-07T08:23:00.001-04:00</published><updated>2008-07-07T08:23:50.236-04:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="svnbackup" /><title type="text">svnbackup 1.5</title><content type="html">Matthew McDonald contributed a patch to let svnbackup work on repositories with spaces in the name.  I also added a --compress option so users can choose between gzip and bzip2 (the default is still bzip2).&lt;br /&gt;&lt;br /&gt;The new release is available from &lt;a href="http://code.google.com/p/svnautobackup/downloads/list"&gt;the download page&lt;/a&gt; at the Google Code project site.&lt;br /&gt;&lt;br /&gt;Thanks, Matthew!&lt;br /&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.doughellmann.com/~f/DougHellmann?a=hgiTjJ"&gt;&lt;img src="http://feeds.doughellmann.com/~f/DougHellmann?i=hgiTjJ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.doughellmann.com/~f/DougHellmann?a=cjySNj"&gt;&lt;img src="http://feeds.doughellmann.com/~f/DougHellmann?i=cjySNj" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.doughellmann.com/~f/DougHellmann?a=s7XPBJ"&gt;&lt;img src="http://feeds.doughellmann.com/~f/DougHellmann?i=s7XPBJ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.doughellmann.com/~f/DougHellmann?a=LRPh9j"&gt;&lt;img src="http://feeds.doughellmann.com/~f/DougHellmann?i=LRPh9j" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.doughellmann.com/~r/DougHellmann/~4/328840470" height="1" width="1"/&gt;</content><link rel="alternate" type="text/html" href="http://feeds.doughellmann.com/~r/DougHellmann/~3/328840470/svnbackup-15.html" title="svnbackup 1.5" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=5440028356946346379&amp;postID=6534219774437987729" title="0 Comments" /><link rel="replies" type="application/atom+xml" href="http://blog.doughellmann.com/feeds/6534219774437987729/comments/default" title="Post Comments" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/5440028356946346379/posts/default/6534219774437987729" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/5440028356946346379/posts/default/6534219774437987729" /><author><name>Doug Hellmann</name><uri>http://www.blogger.com/profile/01892352754222143463</uri><email>noreply@blogger.com</email></author><feedburner:origLink>http://blog.doughellmann.com/2008/07/svnbackup-15.html</feedburner:origLink></entry><entry><id>tag:blogger.com,1999:blog-5440028356946346379.post-5570698782135157739</id><published>2008-07-06T17:06:00.001-04:00</published><updated>2008-07-06T17:06:34.680-04:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="python" /><category scheme="http://www.blogger.com/atom/ns#" term="PyMOTW" /><title type="text">PyMOTW: xmlrpclib</title><content type="html">As a follow-up to &lt;a href="http://blog.doughellmann.com/2008/06/pymotw-simplexmlrpcserver.html"&gt;last week's article on SimpleXMLRPCServer&lt;/a&gt;, this week covers the client-side library xmlrpclib.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Module:&lt;/span&gt; &lt;a href="http://docs.python.org/lib/module-xmlrpclib.html"&gt;xmlrpclib&lt;/a&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Purpose:&lt;/span&gt; Client-side library for XML-RPC communication.&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Python Version:&lt;/span&gt; 2.2 and later&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Description:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Last week we looked at the library for creating an XML-RPC server.  The xmlrpclib module lets you communicate from Python with any XML-RPC server written in any language.  All of the examples below use the server defined in &lt;code&gt;xmlrpclib_server.py&lt;/code&gt;, available in the source distribution and repeated here for reference:&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Connecting to a Server:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;The simplest way to connect a client to a server is to instantiate a ServerProxy object, giving it the URI of the server.  For example, the demo server runs on port 9000 of localhost:&lt;br /&gt;&lt;br /&gt;&lt;div class="syntax"&gt;&lt;pre&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;xmlrpclib&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="n"&gt;server&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;xmlrpclib&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ServerProxy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;http://localhost:9000&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;Ping:&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;server&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ping&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;In this case, the &lt;code&gt;ping()&lt;/code&gt; method of the service takes no arguments and returns a single boolean value.&lt;br /&gt;&lt;br /&gt;&lt;div class="syntax"&gt;&lt;pre&gt;&lt;br /&gt;$ python xmlrpclib_ServerProxy.py&lt;br /&gt;Ping: True&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;Other options are available to support alternate transport.  Both HTTP and HTTPS are supported out of the box, as are basic authentication.  You would only need to provide a transport class if your communication channel was not one of the supported types.  It would be an interesting exercise, for example, to implement XML-RPC over SMTP.  Not terribly useful, but interesting.&lt;br /&gt;&lt;br /&gt;The &lt;em&gt;verbose&lt;/em&gt; option gives you debugging information useful for working out where communication errors might be happening.&lt;br /&gt;&lt;br /&gt;&lt;div class="syntax"&gt;&lt;pre&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;xmlrpclib&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="n"&gt;server&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;xmlrpclib&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ServerProxy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;http://localhost:9000&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;verbose&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;Ping:&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;server&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ping&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;div class="syntax"&gt;&lt;pre&gt;&lt;br /&gt;$ python xmlrpclib_ServerProxy_verbose.py&lt;br /&gt;Ping: connect: (localhost, 9000)&lt;br /&gt;connect fail: ('localhost', 9000)&lt;br /&gt;connect: (localhost, 9000)&lt;br /&gt;connect fail: ('localhost', 9000)&lt;br /&gt;connect: (localhost, 9000)&lt;br /&gt;send: 'POST /RPC2 HTTP/1.0\r\nHost: localhost:9000\r\nUser-Agent: xmlrpclib.py/1.0.1 (by www.pythonware.com)\r\nContent-Type: text/xml\r\nContent-Length: 98\r\n\r\n'&lt;br /&gt;send: "&amp;lt;?xml version='1.0'?&amp;gt;\n&amp;lt;methodCall&amp;gt;\n&amp;lt;methodName&amp;gt;ping&amp;lt;/methodName&amp;gt;\n&amp;lt;params&amp;gt;\n&amp;lt;/params&amp;gt;\n&amp;lt;/methodCall&amp;gt;\n"&lt;br /&gt;reply: 'HTTP/1.0 200 OK\r\n'&lt;br /&gt;header: Server: BaseHTTP/0.3 Python/2.5.1&lt;br /&gt;header: Date: Sun, 06 Jul 2008 19:56:13 GMT&lt;br /&gt;header: Content-type: text/xml&lt;br /&gt;header: Content-length: 129&lt;br /&gt;body: "&amp;lt;?xml version='1.0'?&amp;gt;\n&amp;lt;methodResponse&amp;gt;\n&amp;lt;params&amp;gt;\n&amp;lt;param&amp;gt;\n&amp;lt;value&amp;gt;&amp;lt;boolean&amp;gt;1&amp;lt;/boolean&amp;gt;&amp;lt;/value&amp;gt;\n&amp;lt;/param&amp;gt;\n&amp;lt;/params&amp;gt;\n&amp;lt;/methodResponse&amp;gt;\n"&lt;br /&gt;True&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;You can change the default &lt;em&gt;encoding&lt;/em&gt; from UTF-8 if you need to use an alternate system.&lt;br /&gt;&lt;br /&gt;&lt;div class="syntax"&gt;&lt;pre&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;xmlrpclib&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="n"&gt;server&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;xmlrpclib&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ServerProxy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;http://localhost:9000&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;encoding&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;ISO-8859-1&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;Ping:&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;server&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ping&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;The server should automatically detect the correct encoding.&lt;br /&gt;&lt;br /&gt;&lt;div class="syntax"&gt;&lt;pre&gt;&lt;br /&gt;$ python xmlrpclib_ServerProxy_encoding.py&lt;br /&gt;Ping: True&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;The &lt;em&gt;allow_none&lt;/em&gt; option controls whether Python's &lt;code&gt;None&lt;/code&gt; value is automatically translated to a nil value or if it causes an error.&lt;br /&gt;&lt;br /&gt;&lt;div class="syntax"&gt;&lt;pre&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;xmlrpclib&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="n"&gt;server&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;xmlrpclib&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ServerProxy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;http://localhost:9000&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;allow_none&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;Allowed:&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;server&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;show_type&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="n"&gt;server&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;xmlrpclib&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ServerProxy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;http://localhost:9000&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;allow_none&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;False&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;Not allowed:&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;server&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;show_type&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;Note that the error is raised locally if the client does not allow None, but can also be raised from within the server if it is not configured to allow None.&lt;br /&gt;&lt;br /&gt;&lt;div class="syntax"&gt;&lt;pre&gt;&lt;br /&gt;$ python xmlrpclib_ServerProxy_allow_none.py&lt;br /&gt;Allowed: ['None', "&amp;lt;type 'NoneType'&amp;gt;", None]&lt;br /&gt;Not allowed:&lt;br /&gt;Traceback (most recent call last):&lt;br /&gt;  File "/Users/dhellmann/Documents/PyMOTW/in_progress/xmlrpclib/xmlrpclib_ServerProxy_allow_none.py", line 17, in &amp;lt;module&amp;gt;&lt;br /&gt;    print 'Not allowed:', server.show_type(None)&lt;br /&gt;  File "/Library/Frameworks/Python.framework/Versions/2.5/lib/python2.5/xmlrpclib.py", line 1147, in __call__&lt;br /&gt;    return self.__send(self.__name, args)&lt;br /&gt;  File "/Library/Frameworks/Python.framework/Versions/2.5/lib/python2.5/xmlrpclib.py", line 1431, in __request&lt;br /&gt;    allow_none=self.__allow_none)&lt;br /&gt;  File "/Library/Frameworks/Python.framework/Versions/2.5/lib/python2.5/xmlrpclib.py", line 1080, in dumps&lt;br /&gt;    data = m.dumps(params)&lt;br /&gt;  File "/Library/Frameworks/Python.framework/Versions/2.5/lib/python2.5/xmlrpclib.py", line 623, in dumps&lt;br /&gt;    dump(v, write)&lt;br /&gt;  File "/Library/Frameworks/Python.framework/Versions/2.5/lib/python2.5/xmlrpclib.py", line 635, in __dump&lt;br /&gt;    f(self, value, write)&lt;br /&gt;  File "/Library/Frameworks/Python.framework/Versions/2.5/lib/python2.5/xmlrpclib.py", line 639, in dump_nil&lt;br /&gt;    raise TypeError, "cannot marshal None unless allow_none is enabled"&lt;br /&gt;TypeError: cannot marshal None unless allow_none is enabled&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;The &lt;em&gt;use_datetime&lt;/em&gt; option lets you pass datetime.datetime and related objects in to the proxy or receive them from the server.  If use_datetime is False, the internal DateTime class is used to represent dates instead.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Data Types:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;The XML-RPC protocol recognizes a limited set of common data types.  The types can be passed as arguments or return values and combined to create more complex data structures.&lt;br /&gt;&lt;br /&gt;&lt;div class="syntax"&gt;&lt;pre&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;xmlrpclib&lt;/span&gt;&lt;br /&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;datetime&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="n"&gt;server&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;xmlrpclib&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ServerProxy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;http://localhost:9000&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;v&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;boolean&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;br /&gt;              &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;integer&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;br /&gt;              &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;floating-point number&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;2.5&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;br /&gt;              &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;string&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;some text&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;br /&gt;              &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;datetime&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;datetime&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;datetime&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;now&lt;/span&gt;&lt;span class="p"&gt;()),&lt;/span&gt;&lt;br /&gt;              &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;array&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;a&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;list&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;]),&lt;/span&gt;&lt;br /&gt;              &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;array&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;a&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;tuple&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt;&lt;br /&gt;              &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;structure&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;a&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;dictionary&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;}),&lt;/span&gt;&lt;br /&gt;            &lt;span class="p"&gt;]:&lt;/span&gt;&lt;br /&gt;    &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;&lt;/span&gt;&lt;span class="si"&gt;%-22s&lt;/span&gt;&lt;span class="s"&gt;:&amp;#39;&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;server&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;show_type&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;The simple types:&lt;br /&gt;&lt;br /&gt;&lt;div class="syntax"&gt;&lt;pre&gt;&lt;br /&gt;$ python xmlrpclib_types.py&lt;br /&gt;boolean               : ['True', "&amp;lt;type 'bool'&amp;gt;", True]&lt;br /&gt;integer               : ['1', "&amp;lt;type 'int'&amp;gt;", 1]&lt;br /&gt;floating-point number : ['2.5', "&amp;lt;type 'float'&amp;gt;", 2.5]&lt;br /&gt;string                : ['some text', "&amp;lt;type 'str'&amp;gt;", 'some text']&lt;br /&gt;datetime              : ['20080706T16:22:49', "&amp;lt;type 'instance'&amp;gt;", &amp;lt;DateTime '20080706T16:22:49' at a5d030&amp;gt;]&lt;br /&gt;array                 : ["['a', 'list']", "&amp;lt;type 'list'&amp;gt;", ['a', 'list']]&lt;br /&gt;array                 : ["['a', 'tuple']", "&amp;lt;type 'list'&amp;gt;", ['a', 'tuple']]&lt;br /&gt;structure             : ["{'a': 'dictionary'}", "&amp;lt;type 'dict'&amp;gt;", {'a': 'dictionary'}]&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;And of course, they can be nested to create values of arbitrary complexity:&lt;br /&gt;&lt;br /&gt;&lt;div class="syntax"&gt;&lt;pre&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;xmlrpclib&lt;/span&gt;&lt;br /&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;datetime&lt;/span&gt;&lt;br /&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;pprint&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="n"&gt;server&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;xmlrpclib&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ServerProxy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;http://localhost:9000&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;boolean&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;br /&gt;         &lt;span class="s"&gt;&amp;#39;integer&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;br /&gt;         &lt;span class="s"&gt;&amp;#39;floating-point number&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;2.5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;br /&gt;         &lt;span class="s"&gt;&amp;#39;string&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;some text&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;br /&gt;         &lt;span class="s"&gt;&amp;#39;datetime&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;datetime&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;datetime&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;now&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;&lt;br /&gt;         &lt;span class="s"&gt;&amp;#39;array&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;a&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;list&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;br /&gt;         &lt;span class="s"&gt;&amp;#39;array&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;a&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;tuple&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;br /&gt;         &lt;span class="s"&gt;&amp;#39;structure&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;a&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;dictionary&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;br /&gt;         &lt;span class="p"&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class="n"&gt;arg&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;br /&gt;&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nb"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;br /&gt;    &lt;span class="n"&gt;d&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;&lt;br /&gt;    &lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;update&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;    &lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;integer&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;br /&gt;    &lt;span class="n"&gt;arg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;Before:&amp;#39;&lt;/span&gt;&lt;br /&gt;&lt;span class="n"&gt;pprint&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;pprint&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;arg&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="k"&gt;print&lt;/span&gt;&lt;br /&gt;&lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;After:&amp;#39;&lt;/span&gt;&lt;br /&gt;&lt;span class="n"&gt;pprint&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;pprint&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;server&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;show_type&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;arg&lt;/span&gt;&lt;span class="p"&gt;)[&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;div class="syntax"&gt;&lt;pre&gt;&lt;br /&gt;$ python xmlrpclib_types_nested.py&lt;br /&gt;Before:&lt;br /&gt;[{'array': ('a', 'tuple'),&lt;br /&gt;  'boolean': True,&lt;br /&gt;  'datetime': datetime.datetime(2008, 7, 6, 16, 24, 52, 348849),&lt;br /&gt;  'floating-point number': 2.5,&lt;br /&gt;  'integer': 0,&lt;br /&gt;  'string': 'some text',&lt;br /&gt;  'structure': {'a': 'dictionary'}},&lt;br /&gt; {'array': ('a', 'tuple'),&lt;br /&gt;  'boolean': True,&lt;br /&gt;  'datetime': datetime.datetime(2008, 7, 6, 16, 24, 52, 348849),&lt;br /&gt;  'floating-point number': 2.5,&lt;br /&gt;  'integer': 1,&lt;br /&gt;  'string': 'some text',&lt;br /&gt;  'structure': {'a': 'dictionary'}},&lt;br /&gt; {'array': ('a', 'tuple'),&lt;br /&gt;  'boolean': True,&lt;br /&gt;  'datetime': datetime.datetime(2008, 7, 6, 16, 24, 52, 348849),&lt;br /&gt;  'floating-point number': 2.5,&lt;br /&gt;  'integer': 2,&lt;br /&gt;  'string': 'some text',&lt;br /&gt;  'structure': {'a': 'dictionary'}}]&lt;br /&gt;&lt;br /&gt;After:&lt;br /&gt;[{'array': ['a', 'tuple'],&lt;br /&gt;  'boolean': True,&lt;br /&gt;  'datetime': &amp;lt;DateTime '20080706T16:24:52' at a5be18&amp;gt;,&lt;br /&gt;  'floating-point number': 2.5,&lt;br /&gt;  'integer': 0,&lt;br /&gt;  'string': 'some text',&lt;br /&gt;  'structure': {'a': 'dictionary'}},&lt;br /&gt; {'array': ['a', 'tuple'],&lt;br /&gt;  'boolean': True,&lt;br /&gt;  'datetime': &amp;lt;DateTime '20080706T16:24:52' at a5bf30&amp;gt;,&lt;br /&gt;  'floating-point number': 2.5,&lt;br /&gt;  'integer': 1,&lt;br /&gt;  'string': 'some text',&lt;br /&gt;  'structure': {'a': 'dictionary'}},&lt;br /&gt; {'array': ['a', 'tuple'],&lt;br /&gt;  'boolean': True,&lt;br /&gt;  'datetime': &amp;lt;DateTime '20080706T16:24:52' at a5bf80&amp;gt;,&lt;br /&gt;  'floating-point number': 2.5,&lt;br /&gt;  'integer': 2,&lt;br /&gt;  'string': 'some text',&lt;br /&gt;  'structure': {'a': 'dictionary'}}]&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Passing Objects:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Instances of Python classes are treated as structures and passed as a dictionary, with the attributes of the object as values in the dictionary.&lt;br /&gt;&lt;br /&gt;&lt;div class="syntax"&gt;&lt;pre&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;xmlrpclib&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MyObj&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;br /&gt;    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;br /&gt;        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;br /&gt;        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;br /&gt;    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__repr__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;br /&gt;        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;MyObj(&lt;/span&gt;&lt;span class="si"&gt;%s&lt;/span&gt;&lt;span class="s"&gt;, &lt;/span&gt;&lt;span class="si"&gt;%s&lt;/span&gt;&lt;span class="s"&gt;)&amp;#39;&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;repr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="nb"&gt;repr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="n"&gt;server&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;xmlrpclib&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ServerProxy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;http://localhost:9000&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="n"&gt;o&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;MyObj&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;b goes here&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;o=&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;o&lt;/span&gt;&lt;br /&gt;&lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="n"&gt;server&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;show_type&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;o&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="n"&gt;o2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;MyObj&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;o&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;o2=&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;o2&lt;/span&gt;&lt;br /&gt;&lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="n"&gt;server&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;show_type&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;o2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;Round-tripping the value gives a dictionary on the client, since there is nothing encoded in the values to tell the server (or client) that it should be instantiated as part of a class.&lt;br /&gt;&lt;br /&gt;&lt;div class="syntax"&gt;&lt;pre&gt;&lt;br /&gt;$ python xmlrpclib_types_object.py&lt;br /&gt;o= MyObj(1, 'b goes here')&lt;br /&gt;["{'a': 1, 'b': 'b goes here'}", "&amp;lt;type 'dict'&amp;gt;", {'a': 1, 'b': 'b goes here'}]&lt;br /&gt;o2= MyObj(2, MyObj(1, 'b goes here'))&lt;br /&gt;["{'a': 2, 'b': {'a': 1, 'b': 'b goes here'}}", "&amp;lt;type 'dict'&amp;gt;", {'a': 2, 'b': {'a': 1, 'b': 'b goes here'}}]&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Binary Data:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;All values passed to the server are encoded and escaped automatically.  However, some data types may contain characters that are not valid XML.  For example, binary image data may include byte values in the ASCII control range 0 to 31.  If you need to pass binary data, it is best to use the Binary class to encode it for transport.&lt;br /&gt;&lt;br /&gt;&lt;div class="syntax"&gt;&lt;pre&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;xmlrpclib&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="n"&gt;server&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;xmlrpclib&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ServerProxy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;http://localhost:9000&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;This is a string with control characters&amp;#39;&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;&lt;/span&gt;&lt;span class="se"&gt;\0&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;&lt;/span&gt;&lt;br /&gt;&lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;Local string:&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;xmlrpclib&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Binary&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;As binary:&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;server&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;send_back_binary&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;As string:&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;server&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;show_type&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;If we pass the string containing a NULL byte to show_type(), an exception is raised in the XML parser:&lt;br /&gt;&lt;br /&gt;&lt;div class="syntax"&gt;&lt;pre&gt;&lt;br /&gt;$ python xmlrpclib_Binary.py&lt;br /&gt;Local string: This is a string with control characters&lt;br /&gt;As binary: This is a string with control characters&lt;br /&gt;As string:&lt;br /&gt;Traceback (most recent call last):&lt;br /&gt;  File "/Users/dhellmann/Documents/PyMOTW/in_progress/xmlrpclib/xmlrpclib_Binary.py", line 21, in &amp;lt;module&amp;gt;&lt;br /&gt;    print 'As string:', server.show_type(s)&lt;br /&gt;  File "/Library/Frameworks/Python.framework/Versions/2.5/lib/python2.5/xmlrpclib.py", line 1147, in __call__&lt;br /&gt;    return self.__send(self.__name, args)&lt;br /&gt;  File "/Library/Frameworks/Python.framework/Versions/2.5/lib/python2.5/xmlrpclib.py", line 1437, in __request&lt;br /&gt;    verbose=self.__verbose&lt;br /&gt;  File "/Library/Frameworks/Python.framework/Versions/2.5/lib/python2.5/xmlrpclib.py", line 1201, in request&lt;br /&gt;    return self._parse_response(h.getfile(), sock)&lt;br /&gt;  File "/Library/Frameworks/Python.framework/Versions/2.5/lib/python2.5/xmlrpclib.py", line 1340, in _parse_response&lt;br /&gt;    return u.close()&lt;br /&gt;  File "/Library/Frameworks/Python.framework/Versions/2.5/lib/python2.5/xmlrpclib.py", line 787, in close&lt;br /&gt;    raise Fault(**self._stack[0])&lt;br /&gt;xmlrpclib.Fault: &amp;lt;Fault 1: "&amp;lt;class 'xml.parsers.expat.ExpatError'&amp;gt;:not well-formed (invalid token): line 6, column 55"&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;Binary data can also be used to send objects using pickles.  The normal security issues related to sending what amounts to executable code over the wire apply here (i.e., don't do this unless you're sure your communication channel is secure).&lt;br /&gt;&lt;br /&gt;&lt;div class="syntax"&gt;&lt;pre&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;xmlrpclib&lt;/span&gt;&lt;br /&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;cPickle&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nn"&gt;pickle&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MyObj&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;br /&gt;    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;br /&gt;        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;br /&gt;        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;br /&gt;    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__repr__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;br /&gt;        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;MyObj(&lt;/span&gt;&lt;span class="si"&gt;%s&lt;/span&gt;&lt;span class="s"&gt;, &lt;/span&gt;&lt;span class="si"&gt;%s&lt;/span&gt;&lt;span class="s"&gt;)&amp;#39;&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;repr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="nb"&gt;repr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="n"&gt;server&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;xmlrpclib&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ServerProxy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;http://localhost:9000&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="n"&gt;o&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;MyObj&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;b goes here&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;Local:&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;o&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;o&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;As object:&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;server&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;show_type&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;o&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pickle&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dumps&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;o&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;xmlrpclib&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Binary&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;server&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;send_back_binary&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="n"&gt;o2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pickle&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;loads&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;From pickle:&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;o2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;o2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;Remember, the data attribute of the Binary instance contains the pickled version of the object, so it has to be unpickled before it can be used.  That results in a different object (with a new id value).&lt;br /&gt;&lt;br /&gt;&lt;div class="syntax"&gt;&lt;pre&gt;&lt;br /&gt;$ python xmlrpclib_Binary_pickle.py&lt;br /&gt;Local: MyObj(1, 'b goes here') 9620936&lt;br /&gt;As object: ["{'a': 1, 'b': 'b goes here'}", "&amp;lt;type 'dict'&amp;gt;", {'a': 1, 'b': 'b goes here'}]&lt;br /&gt;From pickle: MyObj(1, 'b goes here') 11049200&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Exception Handling:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Since the XML-RPC server might be written in any language, exception classes cannot be transmitted directly.  Instead, exceptions raised in the server are converted to Fault objects and raised as exceptions locally.&lt;br /&gt;&lt;br /&gt;&lt;div class="syntax"&gt;&lt;pre&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;xmlrpclib&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="n"&gt;server&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;xmlrpclib&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ServerProxy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;http://localhost:9000&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;br /&gt;    &lt;span class="n"&gt;server&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;raises_exception&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;A message&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="ne"&gt;Exception&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;br /&gt;    &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;Fault code:&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;faultCode&lt;/span&gt;&lt;br /&gt;    &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;Message   :&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;faultString&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;div class="syntax"&gt;&lt;pre&gt;&lt;br /&gt;$ python xmlrpclib_exception.py&lt;br /&gt;Fault code: 1&lt;br /&gt;Message   : &amp;lt;type 'exceptions.RuntimeError'&amp;gt;:A message&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;MultiCall:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Multicall is an extension to the XML-RPC protocol to allow more than one call to be sent at the same time, with the responses collected and returned to the caller.  The &lt;code&gt;MultiCall&lt;/code&gt; class was added to xmlrpclib in Python 2.4.  To use a MultiCall instance, invoke the methods on it as with a ServerProxy, then call the object with no arguments.  The result is an iterator with the results.&lt;br /&gt;&lt;br /&gt;&lt;div class="syntax"&gt;&lt;pre&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;xmlrpclib&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="n"&gt;server&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;xmlrpclib&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ServerProxy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;http://localhost:9000&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="n"&gt;multicall&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;xmlrpclib&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;MultiCall&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;server&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class="n"&gt;multicall&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ping&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;br /&gt;&lt;span class="n"&gt;multicall&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;show_type&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class="n"&gt;multicall&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;show_type&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;string&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nb"&gt;enumerate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;multicall&lt;/span&gt;&lt;span class="p"&gt;()):&lt;/span&gt;&lt;br /&gt;    &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;div class="syntax"&gt;&lt;pre&gt;&lt;br /&gt;$ python xmlrpclib_MultiCall.py&lt;br /&gt;0 True&lt;br /&gt;1 ['1', "&amp;lt;type 'int'&amp;gt;", 1]&lt;br /&gt;2 ['string', "&amp;lt;type 'str'&amp;gt;", 'string']&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;If one of the calls causes a Fault or otherwise raises an exception, the exception is raised when the result is produced from the iterator and no more results are available.&lt;br /&gt;&lt;br /&gt;&lt;div class="syntax"&gt;&lt;pre&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;xmlrpclib&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="n"&gt;server&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;xmlrpclib&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ServerProxy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;http://localhost:9000&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="n"&gt;multicall&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;xmlrpclib&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;MultiCall&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;server&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class="n"&gt;multicall&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ping&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;br /&gt;&lt;span class="n"&gt;multicall&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;show_type&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class="n"&gt;multicall&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;raises_exception&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;Next to last call stops execution&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class="n"&gt;multicall&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;show_type&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;string&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nb"&gt;enumerate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;multicall&lt;/span&gt;&lt;span class="p"&gt;()):&lt;/span&gt;&lt;br /&gt;    &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;div class="syntax"&gt;&lt;pre&gt;&lt;br /&gt;$ python xmlrpclib_MultiCall_exception.py&lt;br /&gt;0 True&lt;br /&gt;1 ['1', "&amp;lt;type 'int'&amp;gt;", 1]&lt;br /&gt;Traceback (most recent call last):&lt;br /&gt;  File "/Users/dhellmann/Documents/PyMOTW/in_progress/xmlrpclib/xmlrpclib_MultiCall_exception.py", line 21, in &amp;lt;module&amp;gt;&lt;br /&gt;    for i, r in enumerate(multicall()):&lt;br /&gt;  File "/Library/Frameworks/Python.framework/Versions/2.5/lib/python2.5/xmlrpclib.py", line 949, in __getitem__&lt;br /&gt;    raise Fault(item['faultCode'], item['faultString'])&lt;br /&gt;xmlrpclib.Fault: &amp;lt;Fault 1: "&amp;lt;type 'exceptions.RuntimeError'&amp;gt;:Next to last call stops execution"&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;References:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://blog.doughellmann.com/2008/06/pymotw-simplexmlrpcserver.html"&gt;PyMOTW: SimpleXMLRPCServer&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.tldp.org/HOWTO/XML-RPC-HOWTO/index.html"&gt;XML-RPC How To&lt;/a&gt;&lt;br /&gt;&lt;a href="http://ontosys.com/xml-rpc/extensions.php"&gt;XML-RPC Extensions&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.doughellmann.com/projects/PyMOTW/"&gt;Python Module of the Week Home&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.doughellmann.com/downloads/PyMOTW-1.61.tar.gz"&gt;Download Sample Code&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;!-- Technorati Tags Start --&gt;&lt;br /&gt;&lt;p&gt;Technorati Tags:&lt;br /&gt;&lt;a href="http://technorati.com/tag/python" rel="tag"&gt;python&lt;/a&gt;, &lt;a href="http://technorati.com/tag/PyMOTW" rel="tag"&gt;PyMOTW&lt;/a&gt;&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;!-- Technorati Tags End --&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.doughellmann.com/~f/DougHellmann?a=IRPdEJ"&gt;&lt;img src="http://feeds.doughellmann.com/~f/DougHellmann?i=IRPdEJ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.doughellmann.com/~f/DougHellmann?a=VU93Ej"&gt;&lt;img src="http://feeds.doughellmann.com/~f/DougHellmann?i=VU93Ej" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.doughellmann.com/~f/DougHellmann?a=UgtKIJ"&gt;&lt;img src="http://feeds.doughellmann.com/~f/DougHellmann?i=UgtKIJ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.doughellmann.com/~f/DougHellmann?a=yh9Lkj"&gt;&lt;img src="http://feeds.doughellmann.com/~f/DougHellmann?i=yh9Lkj" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.doughellmann.com/~r/DougHellmann/~4/328311770" height="1" width="1"/&gt;</content><link rel="alternate" type="text/html" href="http://feeds.doughellmann.com/~r/DougHellmann/~3/328311770/pymotw-xmlrpclib.html" title="PyMOTW: xmlrpclib" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=5440028356946346379&amp;postID=5570698782135157739" title="0 Comments" /><link rel="replies" type="application/atom+xml" href="http://blog.doughellmann.com/feeds/5570698782135157739/comments/default" title="Post Comments" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/5440028356946346379/posts/default/5570698782135157739" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/5440028356946346379/posts/default/5570698782135157739" /><author><name>Doug Hellmann</name><uri>http://www.blogger.com/profile/01892352754222143463</uri><email>noreply@blogger.com</email></author><feedburner:origLink>http://blog.doughellmann.com/2008/07/pymotw-xmlrpclib.html</feedburner:origLink></entry><entry><id>tag:blogger.com,1999:blog-5440028356946346379.post-6049699903581591126</id><published>2008-07-01T08:31:00.001-04:00</published><updated>2008-07-01T08:31:58.986-04:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Python Magazine" /><category scheme="http://www.blogger.com/atom/ns#" term="Proctor" /><category scheme="http://www.blogger.com/atom/ns#" term="python" /><title type="text">Automated Testing with unittest and Proctor</title><content type="html">Automated testing is an important part of Agile development methodologies, and the practice is seeing increasing adoption even in environments where other Agile tools are not used. This article discusses testing techniques for you to use with the open source tool Proctor. By using Proctor, you will not only manage your automated test suite more effectively, but you will also obtain better results in the process.&lt;br /&gt;&lt;br /&gt;This article was originally published in &lt;a href="http://www.pythonmagazine.com/"&gt;Python Magazine&lt;/a&gt; in &lt;a href="http://pymag.phparch.com/c/issue/view/70"&gt;March of 2008&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.doughellmann.com/articles/Proctor/index.html"&gt;Read more&lt;/a&gt;&lt;br /&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.doughellmann.com/~f/DougHellmann?a=OSLAHJ"&gt;&lt;img src="http://feeds.doughellmann.com/~f/DougHellmann?i=OSLAHJ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.doughellmann.com/~f/DougHellmann?a=uyOaCj"&gt;&lt;img src="http://feeds.doughellmann.com/~f/DougHellmann?i=uyOaCj" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.doughellmann.com/~f/DougHellmann?a=4EyCZJ"&gt;&lt;img src="http://feeds.doughellmann.com/~f/DougHellmann?i=4EyCZJ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.doughellmann.com/~f/DougHellmann?a=emvkCj"&gt;&lt;img src="http://feeds.doughellmann.com/~f/DougHellmann?i=emvkCj" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.doughellmann.com/~r/DougHellmann/~4/324018969" height="1" width="1"/&gt;</content><link rel="alternate" type="text/html" href="http://feeds.doughellmann.com/~r/DougHellmann/~3/324018969/automated-testing-with-unittest-and.html" title="Automated Testing with unittest and Proctor" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=5440028356946346379&amp;postID=6049699903581591126" title="0 Comments" /><link rel="replies" type="application/atom+xml" href="http://blog.doughellmann.com/feeds/6049699903581591126/comments/default" title="Post Comments" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/5440028356946346379/posts/default/6049699903581591126" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/5440028356946346379/posts/default/6049699903581591126" /><author><name>Doug Hellmann</name><uri>http://www.blogger.com/profile/01892352754222143463</uri><email>noreply@blogger.com</email></author><feedburner:origLink>http://blog.doughellmann.com/2008/07/automated-testing-with-unittest-and.html</feedburner:origLink></entry><entry><id>tag:blogger.com,1999:blog-5440028356946346379.post-6288777938797713899</id><published>2008-06-29T12:28:00.001-04:00</published><updated>2008-06-29T12:28:56.667-04:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="python" /><category scheme="http://www.blogger.com/atom/ns#" term="PyMOTW" /><title type="text">PyMOTW: SimpleXMLRPCServer</title><content type="html">The &lt;code&gt;SimpleXMLRPCServer&lt;/code&gt; module makes it easy to use remote procedure calls in Python that work with many other languages, too.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Module:&lt;/span&gt; &lt;a href="http://docs.python.org/lib/module-SimpleXMLRPCServer.html"&gt;SimpleXMLRPCServer&lt;/a&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Purpose:&lt;/span&gt; Implements an XML-RPC server.&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Python Version:&lt;/span&gt; 2.2 and later&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Description:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;The SimpleXMLRPCServer module contains classes for creating your own cross-platform, language-independent server using the XML-RPC protocol.  Client libraries exist for many other languages, making XML-RPC an easy choice for building RPC-style services.&lt;br /&gt;&lt;br /&gt;&lt;em&gt;Note:&lt;/em&gt; All of the examples provided here include a client module as well to interact with the demonstration server.  If you want to download the code and run the examples, you will want to use 2 separate shell windows, one for the server and one for the client.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;A Simple Server:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;This simple server example exposes a single function that takes the name of a directory and returns the contents (obviously a security issue, but useful for demonstration purposes).  The first step is to create the SimpleXMLRPCServer instance and tell it where to listen for incoming requests ('localhost' port 9000 in this case).  Then we define a function to be part of the service, and register the function so the server knows how to call it.  The final step is to put the server into an infinite loop receiving and responding to requests.&lt;br /&gt;&lt;br /&gt;&lt;div class="syntax"&gt;&lt;pre&gt;&lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;SimpleXMLRPCServer&lt;/span&gt; &lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="n"&gt;SimpleXMLRPCServer&lt;/span&gt;&lt;br /&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;logging&lt;/span&gt;&lt;br /&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;os&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="c"&gt;# Set up logging&lt;/span&gt;&lt;br /&gt;&lt;span class="n"&gt;logging&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;basicConfig&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;level&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;logging&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DEBUG&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="n"&gt;server&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;SimpleXMLRPCServer&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;localhost&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;9000&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;logRequests&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="c"&gt;# Expose a function&lt;/span&gt;&lt;br /&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;list_contents&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dir_name&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;br /&gt;    &lt;span class="n"&gt;logging&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;debug&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;list_contents(&lt;/span&gt;&lt;span class="si"&gt;%s&lt;/span&gt;&lt;span class="s"&gt;)&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;dir_name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;listdir&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dir_name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class="n"&gt;server&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;register_function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;list_contents&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;br /&gt;    &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;Use Control-C to exit&amp;#39;&lt;/span&gt;&lt;br /&gt;    &lt;span class="n"&gt;server&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;serve_forever&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;br /&gt;&lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="ne"&gt;KeyboardInterrupt&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;br /&gt;    &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;Exiting&amp;#39;&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;The server can be accessed at the URL &lt;code&gt;http://localhost:9000&lt;/code&gt; using &lt;code&gt;xmlrpclib&lt;/code&gt;.  This client code illustrates how to call the &lt;code&gt;list_contents()&lt;/code&gt; service from Python.&lt;br /&gt;&lt;br /&gt;&lt;div class="syntax"&gt;&lt;pre&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;xmlrpclib&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="n"&gt;proxy&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;xmlrpclib&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ServerProxy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;http://localhost:9000&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="n"&gt;proxy&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;list_contents&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;/tmp&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;Notice that we simply connect the ServerProxy to the server using its base URL, and then call methods directly on the proxy.  Each method invoked on the proxy is translated into a request to the server.  The arguments are formatted using XML, and then POSTed to the server.  The server unpacks the XML and figures out what function to call based on the method name invoked from the client.  The arguments are passed to the function, and the return value is translated back to XML to be returned to the client.&lt;br /&gt;&lt;br /&gt;Starting the server gives:&lt;br /&gt;&lt;br /&gt;&lt;div class="syntax"&gt;&lt;pre&gt;$ python SimpleXMLRPCServer_function.py &lt;br /&gt;Use Control-C to exit&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;Running the client in a second window shows the contents of my &lt;code&gt;/tmp&lt;/code&gt; directory:&lt;br /&gt;&lt;br /&gt;&lt;div class="syntax"&gt;&lt;pre&gt;$ python SimpleXMLRPCServer_function_client.py &lt;br /&gt;['.s.PGSQL.5432', '.s.PGSQL.5432.lock', '.X0-lock', '.X11-unix', 'ccc_exclude.1mkahl', &lt;br /&gt;'ccc_exclude.BKG3gb', 'ccc_exclude.M5jrgo', 'ccc_exclude.SPecwL', 'com.hp.launchport', 'emacs527',&lt;br /&gt;'hsperfdata_dhellmann', 'launch-8hGHUp', 'launch-RQnlcc', 'launch-trsdly', 'launchd-242.T5UzTy', &lt;br /&gt;'var_backups']&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;and after the request is finished you'll see log output in the server window:&lt;br /&gt;&lt;br /&gt;&lt;div class="syntax"&gt;&lt;pre&gt;$ python SimpleXMLRPCServer_function.py &lt;br /&gt;Use Control-C to exit&lt;br /&gt;DEBUG:root:list_contents(/tmp)&lt;br /&gt;localhost - - [29/Jun/2008 09:32:07] "POST /RPC2 HTTP/1.0" 200 -&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;The first line of output is from the logging.debug() call inside list_contents().  The second line is from the server logging the request because I set logRequests=True.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Alternate Names:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Sometimes the function names you use inside your modules or libraries are not the names you want to use in your external API.  You might need to load a platform-specific implementation, build the service API dynamically based on a configuration file, or replace real functions with stubs for testing.  If you want to register a function with an alternate name, pass the name as the second argument to &lt;code&gt;register_function()&lt;/code&gt;, like this:&lt;br /&gt;&lt;br /&gt;&lt;div class="syntax"&gt;&lt;pre&gt;&lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;SimpleXMLRPCServer&lt;/span&gt; &lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="n"&gt;SimpleXMLRPCServer&lt;/span&gt;&lt;br /&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;os&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="n"&gt;server&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;SimpleXMLRPCServer&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;localhost&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;9000&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="c"&gt;# Expose a function with an alternate name&lt;/span&gt;&lt;br /&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;list_contents&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dir_name&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;br /&gt;    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;listdir&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dir_name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class="n"&gt;server&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;register_function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;list_contents&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;dir&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;br /&gt;    &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;Use Control-C to exit&amp;#39;&lt;/span&gt;&lt;br /&gt;    &lt;span class="n"&gt;server&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;serve_forever&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;br /&gt;&lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="ne"&gt;KeyboardInterrupt&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;br /&gt;    &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;Exiting&amp;#39;&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;The client should now use the name 'dir()' instead of 'list_contents()':&lt;br /&gt;&lt;br /&gt;&lt;div class="syntax"&gt;&lt;pre&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;xmlrpclib&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="n"&gt;proxy&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;xmlrpclib&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ServerProxy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;http://localhost:9000&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;dir():&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;proxy&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dir&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;/tmp&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;list_contents():&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;proxy&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;list_contents&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;/tmp&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;Calling &lt;code&gt;list_contents()&lt;/code&gt; results in an error, since the server no longer has a handler registered by that name.&lt;br /&gt;&lt;br /&gt;&lt;div class="syntax"&gt;&lt;pre&gt;&lt;br /&gt;$ python SimpleXMLRPCServer_alternate_name_client.py&lt;br /&gt;dir(): ['.s.PGSQL.5432', '.s.PGSQL.5432.lock', '.X0-lock', '.X11-unix', 'ccc_exclude.1mkahl', 'ccc_exclude.BKG3gb', 'ccc_exclude.M5jrgo', 'ccc_exclude.SPecwL', 'com.hp.launchport', 'emacs527', 'hsperfdata_dhellmann', 'launch-8hGHUp', 'launch-RQnlcc', 'launch-trsdly', 'launchd-242.T5UzTy', 'temp_textmate.V6YKzm', 'var_backups']&lt;br /&gt;list_contents():&lt;br /&gt;Traceback (most recent call last):&lt;br /&gt;  File "/Users/dhellmann/Documents/PyMOTW/in_progress/SimpleXMLRPCServer/SimpleXMLRPCServer_alternate_name_client.py", line 15, in &amp;lt;module&amp;gt;&lt;br /&gt;    print 'list_contents():', proxy.list_contents('/tmp')&lt;br /&gt;  File "/Library/Frameworks/Python.framework/Versions/2.5/lib/python2.5/xmlrpclib.py", line 1147, in __call__&lt;br /&gt;    return self.__send(self.__name, args)&lt;br /&gt;  File "/Library/Frameworks/Python.framework/Versions/2.5/lib/python2.5/xmlrpclib.py", line 1437, in __request&lt;br /&gt;    verbose=self.__verbose&lt;br /&gt;  File "/Library/Frameworks/Python.framework/Versions/2.5/lib/python2.5/xmlrpclib.py", line 1201, in request&lt;br /&gt;    return self._parse_response(h.getfile(), sock)&lt;br /&gt;  File "/Library/Frameworks/Python.framework/Versions/2.5/lib/python2.5/xmlrpclib.py", line 1340, in _parse_response&lt;br /&gt;    return u.close()&lt;br /&gt;  File "/Library/Frameworks/Python.framework/Versions/2.5/lib/python2.5/xmlrpclib.py", line 787, in close&lt;br /&gt;    raise Fault(**self._stack[0])&lt;br /&gt;xmlrpclib.Fault: &amp;lt;Fault 1: '&amp;lt;type \'exceptions.Exception\'&amp;gt;:method "list_contents" is not supported'&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Dotted Names:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Individual functions can be registered with names that are not normally legal for Python identifiers.  For example, you can include '.' in your names to separate the namespace in the service.  This example extends our "directory" service to add "create" and "remove" calls.  All of the functions are registered using the prefix "dir." so that the same server can provide other services using a different prefix.  One other difference in this example is that some of the functions return &lt;code&gt;None&lt;/code&gt;, so we have to tell the server to translate the None values to a nil value (see &lt;a href="http://ontosys.com/xml-rpc/extensions.php"&gt;XML-RPC Extensions&lt;/a&gt;).&lt;br /&gt;&lt;br /&gt;&lt;div class="syntax"&gt;&lt;pre&gt;&lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;SimpleXMLRPCServer&lt;/span&gt; &lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="n"&gt;SimpleXMLRPCServer&lt;/span&gt;&lt;br /&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;os&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="n"&gt;server&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;SimpleXMLRPCServer&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;localhost&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;9000&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;allow_none&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="n"&gt;server&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;register_function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;listdir&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;dir.list&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class="n"&gt;server&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;register_function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;mkdir&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;dir.create&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class="n"&gt;server&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;register_function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;rmdir&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;dir.remove&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;br /&gt;    &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;Use Control-C to exit&amp;#39;&lt;/span&gt;&lt;br /&gt;    &lt;span class="n"&gt;server&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;serve_forever&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;br /&gt;&lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="ne"&gt;KeyboardInterrupt&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;br /&gt;    &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;Exiting&amp;#39;&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;To call the service functions in the client, simply refer to them with the dotted name, like so:&lt;br /&gt;&lt;br /&gt;&lt;div class="syntax"&gt;&lt;pre&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;xmlrpclib&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="n"&gt;proxy&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;xmlrpclib&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ServerProxy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;http://localhost:9000&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;BEFORE       :&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;EXAMPLE&amp;#39;&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;proxy&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dir&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;list&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;/tmp&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;CREATE       :&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;proxy&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dir&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;/tmp/EXAMPLE&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;SHOULD EXIST :&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;EXAMPLE&amp;#39;&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;proxy&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dir&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;list&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;/tmp&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;REMOVE       :&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;proxy&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dir&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;remove&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;/tmp/EXAMPLE&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;AFTER        :&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;EXAMPLE&amp;#39;&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;proxy&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dir&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;list&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;/tmp&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;and (assuming you don't have a /tmp/EXAMPLE on your system) the output for the sample client script looks like:&lt;br /&gt;&lt;br /&gt;&lt;div class="syntax"&gt;&lt;pre&gt;&lt;br /&gt;$ python SimpleXMLRPCServer_dotted_name_client.py&lt;br /&gt;BEFORE       : False&lt;br /&gt;CREATE       : None&lt;br /&gt;SHOULD EXIST : True&lt;br /&gt;REMOVE       : None&lt;br /&gt;AFTER        : False&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Arbitrary Names:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;A less useful, but potentially interesting feature is the ability to register functions with names that are otherwise invalid attribute names.  This example service registers a function with the name "multiply args".&lt;br /&gt;&lt;br /&gt;&lt;div class="syntax"&gt;&lt;pre&gt;&lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;SimpleXMLRPCServer&lt;/span&gt; &lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="n"&gt;SimpleXMLRPCServer&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="n"&gt;server&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;SimpleXMLRPCServer&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;localhost&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;9000&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;my_function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;br /&gt;    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;br /&gt;&lt;span class="n"&gt;server&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;register_function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;my_function&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;multiply args&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;br /&gt;    &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;Use Control-C to exit&amp;#39;&lt;/span&gt;&lt;br /&gt;    &lt;span class="n"&gt;server&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;serve_forever&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;br /&gt;&lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="ne"&gt;KeyboardInterrupt&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;br /&gt;    &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;Exiting&amp;#39;&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;Since the registered name contains a space, we can't use dot notation to access it directly from the proxy.  We can, however, use &lt;code&gt;getattr()&lt;/code&gt;.&lt;br /&gt;&lt;br /&gt;&lt;div class="syntax"&gt;&lt;pre&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;xmlrpclib&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="n"&gt;proxy&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;xmlrpclib&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ServerProxy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;http://localhost:9000&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="nb"&gt;getattr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;proxy&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;multiply args&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;This example is provide not necessarily because it is a good idea, but because you may encounter existing services with arbitrary names and need to be able to call them.&lt;br /&gt;&lt;br /&gt;&lt;div class="syntax"&gt;&lt;pre&gt;&lt;br /&gt;$ python SimpleXMLRPCServer_arbitrary_name_client.py&lt;br /&gt;25&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Exposing Methods of Objects:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;We've talked about establishing APIs using good naming conventions.  Another way to do that is to use instances of classes and expose their methods.  We can recreate the first example using an instance with a single method.&lt;br /&gt;&lt;br /&gt;&lt;div class="syntax"&gt;&lt;pre&gt;&lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;SimpleXMLRPCServer&lt;/span&gt; &lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="n"&gt;SimpleXMLRPCServer&lt;/span&gt;&lt;br /&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;os&lt;/span&gt;&lt;br /&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;inspect&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="n"&gt;server&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;SimpleXMLRPCServer&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;localhost&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;9000&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;logRequests&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;DirectoryService&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;br /&gt;    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;list&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;dir_name&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;br /&gt;        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;listdir&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dir_name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="n"&gt;server&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;register_instance&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;DirectoryService&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;br /&gt;    &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;Use Control-C to exit&amp;#39;&lt;/span&gt;&lt;br /&gt;    &lt;span class="n"&gt;server&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;serve_forever&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;br /&gt;&lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="ne"&gt;KeyboardInterrupt&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;br /&gt;    &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;Exiting&amp;#39;&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;A client can call the method directly:&lt;br /&gt;&lt;br /&gt;&lt;div class="syntax"&gt;&lt;pre&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;xmlrpclib&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="n"&gt;proxy&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;xmlrpclib&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ServerProxy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;http://localhost:9000&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="n"&gt;proxy&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;list&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;/tmp&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;and receive output like:&lt;br /&gt;&lt;br /&gt;&lt;div class="syntax"&gt;&lt;pre&gt;&lt;br /&gt;$ python SimpleXMLRPCServer_instance_client.py&lt;br /&gt;['.s.PGSQL.5432', '.s.PGSQL.5432.lock', '.X0-lock', '.X11-unix', 'ccc_exclude.1mkahl', &lt;br /&gt;'ccc_exclude.BKG3gb', 'ccc_exclude.M5jrgo', 'ccc_exclude.SPecwL', 'com.hp.launchport', &lt;br /&gt;'emacs527', 'hsperfdata_dhellmann', 'launch-8hGHUp', 'launch-RQnlcc', 'launch-trsdly', &lt;br /&gt;'launchd-242.T5UzTy', 'temp_textmate.XNiIdy', 'var_backups']&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;We've lost the 'dir.' prefix for the service, though, so let's define a class to let us set up a service tree that can be invoked from clients.&lt;br /&gt;&lt;br /&gt;&lt;div class="syntax"&gt;&lt;pre&gt;&lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;SimpleXMLRPCServer&lt;/span&gt; &lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="n"&gt;SimpleXMLRPCServer&lt;/span&gt;&lt;br /&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;os&lt;/span&gt;&lt;br /&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;inspect&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="n"&gt;server&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;SimpleXMLRPCServer&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;localhost&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;9000&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;logRequests&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ServiceRoot&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;br /&gt;    &lt;span class="k"&gt;pass&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;DirectoryService&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;br /&gt;    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;list&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;dir_name&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;br /&gt;        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;listdir&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dir_name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="n"&gt;root&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ServiceRoot&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;br /&gt;&lt;span class="n"&gt;root&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dir&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;DirectoryService&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="n"&gt;server&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;register_instance&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;root&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;allow_dotted_names&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;br /&gt;    &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;Use Control-C to exit&amp;#39;&lt;/span&gt;&lt;br /&gt;    &lt;span class="n"&gt;server&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;serve_forever&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;br /&gt;&lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="ne"&gt;KeyboardInterrupt&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;br /&gt;    &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;Exiting&amp;#39;&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;By registering the instance of ServiceRoot with allow_dotted_names=True, we give the server permission to walk the tree of objects when a request comes in to find the named method using getattr().&lt;br /&gt;&lt;br /&gt;&lt;div class="syntax"&gt;&lt;pre&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;xmlrpclib&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="n"&gt;proxy&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;xmlrpclib&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ServerProxy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;http://localhost:9000&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="n"&gt;proxy&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dir&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;list&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;/tmp&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;div class="syntax"&gt;&lt;pre&gt;&lt;br /&gt;$ python SimpleXMLRPCServer_instance_dotted_names_client.py&lt;br /&gt;['.s.PGSQL.5432', '.s.PGSQL.5432.lock', '.X0-lock', '.X11-unix', 'ccc_exclude.1mkahl', 'ccc_exclude.BKG3gb', 'ccc_exclude.M5jrgo', 'ccc_exclude.SPecwL', 'com.hp.launchport', 'emacs527', 'hsperfdata_dhellmann', 'launch-8hGHUp', 'launch-RQnlcc', 'launch-trsdly', 'launchd-242.T5UzTy', 'temp_textmate.adghkQ', 'var_backups']&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Dispatching Calls Yourself:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;By default &lt;code&gt;register_instance()&lt;/code&gt; finds all callable attributes of the instance with names not starting with '_' and registers them with their name.  If you want to be more careful about the exposed methods, you could provide your own dispatching logic.  For example:&lt;br /&gt;&lt;br /&gt;&lt;div class="syntax"&gt;&lt;pre&gt;&lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;SimpleXMLRPCServer&lt;/span&gt; &lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="n"&gt;SimpleXMLRPCServer&lt;/span&gt;&lt;br /&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;os&lt;/span&gt;&lt;br /&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;inspect&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="n"&gt;server&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;SimpleXMLRPCServer&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;localhost&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;9000&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;logRequests&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;expose&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;br /&gt;    &lt;span class="s"&gt;&amp;quot;Decorator to set exposed flag on a function.&amp;quot;&lt;/span&gt;&lt;br /&gt;    &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;exposed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;&lt;br /&gt;    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;is_exposed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;br /&gt;    &lt;span class="s"&gt;&amp;quot;Test whether another function should be publicly exposed.&amp;quot;&lt;/span&gt;&lt;br /&gt;    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;getattr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;exposed&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="bp"&gt;False&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MyService&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;br /&gt;    &lt;span class="n"&gt;PREFIX&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;prefix&amp;#39;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;_dispatch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;method&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;br /&gt;        &lt;span class="c"&gt;# Remove our prefix from the method name&lt;/span&gt;&lt;br /&gt;        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;method&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;startswith&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;PREFIX&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;.&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;br /&gt;            &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="ne"&gt;Exception&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;method &amp;quot;&lt;/span&gt;&lt;span class="si"&gt;%s&lt;/span&gt;&lt;span class="s"&gt;&amp;quot; is not supported&amp;#39;&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="n"&gt;method&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;        &lt;br /&gt;        &lt;span class="n"&gt;method_name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;method&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;partition&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;.&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)[&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;br /&gt;        &lt;span class="n"&gt;func&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;getattr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;method_name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;            &lt;br /&gt;        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;is_exposed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;func&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;br /&gt;            &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="ne"&gt;Exception&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;method &amp;quot;&lt;/span&gt;&lt;span class="si"&gt;%s&lt;/span&gt;&lt;span class="s"&gt;&amp;quot; is not supported&amp;#39;&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="n"&gt;method&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;        &lt;br /&gt;        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    &lt;span class="nd"&gt;@expose&lt;/span&gt;&lt;br /&gt;    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;public&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;br /&gt;        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;This is public&amp;#39;&lt;/span&gt;&lt;br /&gt;        &lt;br /&gt;    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;private&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;br /&gt;        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;This is private&amp;#39;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="n"&gt;server&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;register_instance&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;MyService&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;br /&gt;    &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;Use Control-C to exit&amp;#39;&lt;/span&gt;&lt;br /&gt;    &lt;span class="n"&gt;server&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;serve_forever&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;br /&gt;&lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="ne"&gt;KeyboardInterrupt&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;br /&gt;    &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;Exiting&amp;#39;&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;The &lt;code&gt;public()&lt;/code&gt; method of MyService is marked as exposed to the XML-RPC service while &lt;code&gt;private()&lt;/code&gt; is not.  The &lt;code&gt;_dispatch()&lt;/code&gt; method is invoked when the client tries to access a function that is part of MyService.  It first enforces the use of a prefix ("prefix." in this case, but you can use anything, of course).  Then it requires the function to have an attribute called "exposed" with a true value.  The exposed flag is set on a function using a decorator for convenience.&lt;br /&gt;&lt;br /&gt;Here are a few sample client calls:&lt;br /&gt;&lt;br /&gt;&lt;div class="syntax"&gt;&lt;pre&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;xmlrpclib&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="n"&gt;proxy&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;xmlrpclib&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ServerProxy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;http://localhost:9000&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;public():&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;proxy&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;prefix&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;public&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;br /&gt;&lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;br /&gt;    &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;private():&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;proxy&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;prefix&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;private&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;br /&gt;&lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="ne"&gt;Exception&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;br /&gt;    &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;ERROR:&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt;&lt;br /&gt;&lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;br /&gt;    &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;public() without prefix:&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;proxy&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;public&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;br /&gt;&lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="ne"&gt;Exception&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;br /&gt;    &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;ERROR:&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;and the resulting output, with the expected error messages trapped and reported:&lt;br /&gt;&lt;br /&gt;&lt;div class="syntax"&gt;&lt;pre&gt;&lt;br /&gt;$ python SimpleXMLRPCServer_instance_with_prefix_client.py&lt;br /&gt;public(): This is public&lt;br /&gt;private(): ERROR: &amp;lt;Fault 1: '&amp;lt;type \'exceptions.Exception\'&amp;gt;:method "prefix.private" is not supported'&amp;gt;&lt;br /&gt;public() without prefix: ERROR: &amp;lt;Fault 1: '&amp;lt;type \'exceptions.Exception\'&amp;gt;:method "public" is not supported'&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;There are several other ways to override the dispatching mechanism, including subclassing directly from SimpleXMLRPCServer.  Check out the docstrings in the module for more details.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Introspection API:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;As with many network services, it is possible to query an XML-RPC server to ask it what methods it supports and learn how to use them.  SimpleXMLRPCServer includes a set of public methods for performing this introspection.  By default they are turned off, but can be enabled with &lt;code&gt;register_introspection_functions()&lt;/code&gt;.  You can add explicit support for &lt;code&gt;system.listMethods()&lt;/code&gt; and &lt;code&gt;system.methodHelp()&lt;/code&gt; by defining &lt;code&gt;_listMethods()&lt;/code&gt; and &lt;code&gt;_methodHelp()&lt;/code&gt; on your service class.  For example,&lt;br /&gt;&lt;br /&gt;&lt;div class="syntax"&gt;&lt;pre&gt;&lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;SimpleXMLRPCServer&lt;/span&gt; &lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="n"&gt;SimpleXMLRPCServer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;list_public_methods&lt;/span&gt;&lt;br /&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;os&lt;/span&gt;&lt;br /&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;inspect&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="n"&gt;server&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;SimpleXMLRPCServer&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;localhost&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;9000&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;logRequests&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class="n"&gt;server&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;register_introspection_functions&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;DirectoryService&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;br /&gt;    &lt;br /&gt;    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;_listMethods&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;br /&gt;        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;list_public_methods&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;_methodHelp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;method&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;br /&gt;        &lt;span class="n"&gt;f&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;getattr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;method&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;inspect&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;getdoc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;    &lt;br /&gt;    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;list&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;dir_name&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;br /&gt;        &lt;span class="sd"&gt;&amp;quot;&amp;quot;&amp;quot;list(dir_name) =&amp;gt; [&amp;lt;filenames&amp;gt;]&lt;/span&gt;&lt;br /&gt;&lt;span class="sd"&gt;        &lt;/span&gt;&lt;br /&gt;&lt;span class="sd"&gt;        Returns a list containing the contents of the named directory.&lt;/span&gt;&lt;br /&gt;&lt;span class="sd"&gt;        &amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;&lt;br /&gt;        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;listdir&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dir_name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="n"&gt;server&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;register_instance&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;DirectoryService&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;br /&gt;    &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;Use Control-C to exit&amp;#39;&lt;/span&gt;&lt;br /&gt;    &lt;span class="n"&gt;server&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;serve_forever&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;br /&gt;&lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="ne"&gt;KeyboardInterrupt&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;br /&gt;    &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;Exiting&amp;#39;&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;In this case, the convenience function &lt;code&gt;list_public_methods()&lt;/code&gt; scans an instance to return the names of callable attributes that do not start with '_'.  You can, of course, redefine &lt;code&gt;_listMethods()&lt;/code&gt; to apply whatever rules you like.  Similarly, for this basic example &lt;code&gt;_methodHelp()&lt;/code&gt; returns the docstring of the function, but could be written to build a help string from any information you like.&lt;br /&gt;&lt;br /&gt;This client queries the server and reports on all of the publicly callable methods.&lt;br /&gt;&lt;br /&gt;&lt;div class="syntax"&gt;&lt;pre&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;xmlrpclib&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="n"&gt;proxy&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;xmlrpclib&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ServerProxy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;http://localhost:9000&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;method_name&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;proxy&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;system&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;listMethods&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;&lt;br /&gt;    &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;=&amp;#39;&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;60&lt;/span&gt;&lt;br /&gt;    &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="n"&gt;method_name&lt;/span&gt;&lt;br /&gt;    &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;-&amp;#39;&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;60&lt;/span&gt;&lt;br /&gt;    &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="n"&gt;proxy&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;system&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;methodHelp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;method_name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;    &lt;span class="k"&gt;print&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;Notice that the &lt;code&gt;system&lt;/code&gt; methods are included in the results.&lt;br /&gt;&lt;br /&gt;&lt;div class="syntax"&gt;&lt;pre&gt;&lt;br /&gt;$ python SimpleXMLRPCServer_introspection_client.py&lt;br /&gt;============================================================&lt;br /&gt;list&lt;br /&gt;------------------------------------------------------------&lt;br /&gt;list(dir_name) =&amp;gt; [&amp;lt;filenames&amp;gt;]&lt;br /&gt;&lt;br /&gt;Returns a list containing the contents of the named directory.&lt;br /&gt;&lt;br /&gt;============================================================&lt;br /&gt;system.listMethods&lt;br /&gt;------------------------------------------------------------&lt;br /&gt;system.listMethods() =&amp;gt; ['add', 'subtract', 'multiple']&lt;br /&gt;&lt;br /&gt;Returns a list of the methods supported by the server.&lt;br /&gt;&lt;br /&gt;============================================================&lt;br /&gt;system.methodHelp&lt;br /&gt;------------------------------------------------------------&lt;br /&gt;system.methodHelp('add') =&amp;gt; "Adds two integers together"&lt;br /&gt;&lt;br /&gt;Returns a string containing documentation for the specified method.&lt;br /&gt;&lt;br /&gt;============================================================&lt;br /&gt;system.methodSignature&lt;br /&gt;------------------------------------------------------------&lt;br /&gt;system.methodSignature('add') =&amp;gt; [double, int, int]&lt;br /&gt;&lt;br /&gt;Returns a list describing the signature of the method. In the&lt;br /&gt;above example, the add method takes two integers as arguments&lt;br /&gt;and returns a double result.&lt;br /&gt;&lt;br /&gt;This server does NOT support system.methodSignature.&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;References:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.tldp.org/HOWTO/XML-RPC-HOWTO/index.html"&gt;XML-RPC How To&lt;/a&gt;&lt;br /&gt;&lt;a href="http://ontosys.com/xml-rpc/extensions.php"&gt;XML-RPC Extensions&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.doughellmann.com/projects/PyMOTW/"&gt;Python Module of the Week Home&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.doughellmann.com/downloads/PyMOTW-1.60.tar.gz"&gt;Download Sample Code&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;!-- Technorati Tags Start --&gt;&lt;br /&gt;&lt;p&gt;Technorati Tags:&lt;br /&gt;&lt;a href="http://technorati.com/tag/python" rel="tag"&gt;python&lt;/a&gt;, &lt;a href="http://technorati.com/tag/PyMOTW" rel="tag"&gt;PyMOTW&lt;/a&gt;&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;!-- Technorati Tags End --&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.doughellmann.com/~f/DougHellmann?a=UrDjQI"&gt;&lt;img src="http://feeds.doughellmann.com/~f/DougHellmann?i=UrDjQI" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.doughellmann.com/~f/DougHellmann?a=uvO0vi"&gt;&lt;img src="http://feeds.doughellmann.com/~f/DougHellmann?i=uvO0vi" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.doughellmann.com/~f/DougHellmann?a=0eLHqI"&gt;&lt;img src="http://feeds.doughellmann.com/~f/DougHellmann?i=0eLHqI" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.doughellmann.com/~f/DougHellmann?a=WP9pti"&gt;&lt;img src="http://feeds.doughellmann.com/~f/DougHellmann?i=WP9pti" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.doughellmann.com/~r/DougHellmann/~4/322664646" height="1" width="1"/&gt;</content><link rel="alternate" type="text/html" href="http://feeds.doughellmann.com/~r/DougHellmann/~3/322664646/pymotw-simplexmlrpcserver.html" title="PyMOTW: SimpleXMLRPCServer" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=5440028356946346379&amp;postID=6288777938797713899" title="1 Comments" /><link rel="replies" type="application/atom+xml" href="http://blog.doughellmann.com/feeds/6288777938797713899/comments/default" title="Post Comments" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/5440028356946346379/posts/default/6288777938797713899" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/5440028356946346379/posts/default/6288777938797713899" /><author><name>Doug Hellmann</name><uri>http://www.blogger.com/profile/01892352754222143463</uri><email>noreply@blogger.com</email></author><feedburner:origLink>http://blog.doughellmann.com/2008/06/pymotw-simplexmlrpcserver.html</feedburner:origLink></entry><entry><id>tag:blogger.com,1999:blog-5440028356946346379.post-2815581942338404510</id><published>2008-06-26T07:24:00.001-04:00</published><updated>2008-06-26T07:24:25.819-04:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Python Magazine" /><category scheme="http://www.blogger.com/atom/ns#" term="python" /><title type="text">PyWorks 2008: Call for papers</title><content type="html">&lt;a href="http://pyworks.mtacon.com/"&gt;&lt;img src="http://pyworks.mtacon.com/img/pyworks/template/logo.png" align="left"&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;MTA, publishers of Python Magazine, are pleased to announce the first &lt;a href="http://pyworks.mtacon.com/"&gt;PyWorks&lt;/a&gt; conference to be held in Atlanta, GA on November 12-14, 2008.&lt;br /&gt;&lt;br /&gt;We are currently looking for speakers and tutorial instructors on a wide range of topics.  The deadline for proposals is July 25, so check out &lt;a href="http://pyworks.mtacon.com/c/p/pyworks,cfp"&gt;the site&lt;/a&gt; for details about how to submit yours today!&lt;br /&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.doughellmann.com/~f/DougHellmann?a=s0Bs8I"&gt;&lt;img src="http://feeds.doughellmann.com/~f/DougHellmann?i=s0Bs8I" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.doughellmann.com/~f/DougHellmann?a=zxu8Qi"&gt;&lt;img src="http://feeds.doughellmann.com/~f/DougHellmann?i=zxu8Qi" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.doughellmann.com/~f/DougHellmann?a=m0ZFNI"&gt;&lt;img src="http://feeds.doughellmann.com/~f/DougHellmann?i=m0ZFNI" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.doughellmann.com/~f/DougHellmann?a=nmZWKi"&gt;&lt;img src="http://feeds.doughellmann.com/~f/DougHellmann?i=nmZWKi" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.doughellmann.com/~r/DougHellmann/~4/320460273" height="1" width="1"/&gt;</content><link rel="alternate" type="text/html" href="http://feeds.doughellmann.com/~r/DougHellmann/~3/320460273/pyworks-2008-call-for-papers.html" title="PyWorks 2008: Call for papers" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=5440028356946346379&amp;postID=2815581942338404510" title="0 Comments" /><link rel="replies" type="application/atom+xml" href="http://blog.doughellmann.com/feeds/2815581942338404510/comments/default" title="Post Comments" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/5440028356946346379/posts/default/2815581942338404510" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/5440028356946346379/posts/default/2815581942338404510" /><author><name>Doug Hellmann</name><uri>http://www.blogger.com/profile/01892352754222143463</uri><email>noreply@blogger.com</email></author><feedburner:origLink>http://blog.doughellmann.com/2008/06/pyworks-2008-call-for-papers.html</feedburner:origLink></entry><entry><id>tag:blogger.com,1999:blog-5440028356946346379.post-198154246119075832</id><published>2008-06-26T07:17:00.001-04:00</published><updated>2008-06-26T07:17:44.318-04:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Python Magazine" /><category scheme="http://www.blogger.com/atom/ns#" term="python" /><title type="text">Python Magazine for June 2008</title><content type="html">&lt;a href="http://pymag.phparch.com/c/issue/view/75"&gt;&lt;img src="http://pymag.phparch.com/img/pymag/issues/thumbnails/75.jpg"  align="right" style="margin: 1em"&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;The &lt;a href="http://pymag.phparch.com/c/issue/view/75"&gt;June issue&lt;/a&gt; is available for download now.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://agiletesting.blogspot.com/"&gt;Grig Gheorghiu's&lt;/a&gt; cover story on &lt;a href="http://www.pybots.org/"&gt;Pybots&lt;/a&gt; talks about the fantastic automation system that has been put in place to make sure new releases of Python software are as robust and stable as possible.&lt;br /&gt;&lt;br /&gt;In the second part of his PyGame series, Terry Hancock adds some interactivity to the simple game he started building in the May issue.  This tutorial is shaping up to be a great introduction for new programmers.&lt;br /&gt;&lt;br /&gt;JC Cruz returns this month with another article on combining Python and OS X.  This time, he shows us how to create a Cocoa application with PyObjC and Xcode 3.0.  This is a topic I've been wanting to dig into myself for some time, so I was glad to have a chance to read his article.&lt;br /&gt;&lt;br /&gt;And rounding out the features this month, Massimo Di Pierro introduces &lt;a href="http://mdp.cti.depaul.edu/"&gt;web2py&lt;/a&gt;, a relative newcomer on the web framework front.  While originally designed primarily as a teaching tool, Massimo explains why that includes many features that make it attractive for rapid application development situations, too.&lt;br /&gt;&lt;br /&gt;Our columns this month are all about the future:&lt;br /&gt;&lt;br /&gt;Mark Mruss takes us quite literally into the &lt;code&gt;__future__&lt;/code&gt; by talking about how to take advantage of some features of Python 3.0 that are already available now in Python 2.5.  &lt;br /&gt;&lt;br /&gt;Jesse Noller talks with Adam Olsen about the &lt;a href="http://code.google.com/p/python-safethread/"&gt;"safe thread"&lt;/a&gt; project, a set of patches for the C interpreter that eliminate the Global Interpreter Lock and that may eventually be included in the Python core.&lt;br /&gt;&lt;br /&gt;Steve Holden responds to Tim Bray's post &lt;a href="http://www.tbray.org/ongoing/When/200x/2008/04/24/Inflection"&gt;Multi-Inflection-Point Alert&lt;/a&gt; by fixing his attention on a few technology trends and looking for portents in their convergence.  &lt;br /&gt;&lt;br /&gt;And finally, this issue also marks the transition as I take over from &lt;a href="http://www.protocolostomy.com/"&gt;Brian Jones&lt;/a&gt; as Editor in Chief.  I want to thank Brian for all he has done to teach me about the position and magazines in general.  I'm looking forward to working with the excellent team of reviewers and editors we have put together as we continue to shape the magazine to be something we can all be proud to be a part of.  &lt;br /&gt;&lt;br /&gt;I'll give more details about our road ahead in another post, but for the time being go download the June issue and enjoy!&lt;br /&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.doughellmann.com/~f/DougHellmann?a=m5L5TI"&gt;&lt;img src="http://feeds.doughellmann.com/~f/DougHellmann?i=m5L5TI" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.doughellmann.com/~f/DougHellmann?a=KZrvIi"&gt;&lt;img src="http://feeds.doughellmann.com/~f/DougHellmann?i=KZrvIi" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.doughellmann.com/~f/DougHellmann?a=rz1abI"&gt;&lt;img src="http://feeds.doughellmann.com/~f/DougHellmann?i=rz1abI" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.doughellmann.com/~f/DougHellmann?a=kzFzTi"&gt;&lt;img src="http://feeds.doughellmann.com/~f/DougHellmann?i=kzFzTi" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.doughellmann.com/~r/DougHellmann/~4/320450616" height="1" width="1"/&gt;</content><link rel="alternate" type="text/html" href="http://feeds.doughellmann.com/~r/DougHellmann/~3/320450616/python-magazine-for-june-2008.html" title="Python Magazine for June 2008" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=5440028356946346379&amp;postID=198154246119075832" title="7 Comments" /><link rel="replies" type="application/atom+xml" href="http://blog.doughellmann.com/feeds/198154246119075832/comments/default" title="Post Comments" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/5440028356946346379/posts/default/198154246119075832" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/5440028356946346379/posts/default/198154246119075832" /><author><name>Doug Hellmann</name><uri>http://www.blogger.com/profile/01892352754222143463</uri><email>noreply@blogger.com</email></author><feedburner:origLink>http://blog.doughellmann.com/2008/06/python-magazine-for-june-2008.html</feedburner:origLink></entry><entry><id>tag:blogger.com,1999:blog-5440028356946346379.post-2636134930545720461</id><published>2008-06-22T12:55:00.001-04:00</published><updated>2008-06-22T12:55:22.262-04:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="svnbackup" /><title type="text">svnbackup news</title><content type="html">I've received several patches for svnbackup.sh recently, and an offer to host an RPM version of the code.  I decided it probably made sense to go ahead and open the project up to contributors, so I created &lt;a href="http://code.google.com/p/svnautobackup/"&gt;a project on code.google.com&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Unfortunately, the name svnbackup was already taken, and svnbackup.sh wasn't a valid project name.  I'm linking from my site to the new project, though, so hopefully the minor name change won't be too confusing.&lt;br /&gt;&lt;br /&gt;Since I had the project on my local svn repository, and not in its own repo, importing the history into google's svn repository was something of a pain.  I'm glad there are only a few files in the source tree.&lt;br /&gt;&lt;br /&gt;There's a new release today, as well.  Version 1.4 includes patches from Arjen Van Drie to fix unary&lt;br /&gt;operator problems and an empty history file bug.  See the &lt;a href="http://code.google.com/p/svnautobackup/downloads/list"&gt;downloads page&lt;/a&gt; for a tarball.&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.doughellmann.com/~f/DougHellmann?a=tcUGRI"&gt;&lt;img src="http://feeds.doughellmann.com/~f/DougHellmann?i=tcUGRI" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.doughellmann.com/~f/DougHellmann?a=uHRXmi"&gt;&lt;img src="http://feeds.doughellmann.com/~f/DougHellmann?i=uHRXmi" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.doughellmann.com/~f/DougHellmann?a=wlsATI"&gt;&lt;img src="http://feeds.doughellmann.com/~f/DougHellmann?i=wlsATI" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.doughellmann.com/~f/DougHellmann?a=LsCWzi"&gt;&lt;img src="http://feeds.doughellmann.com/~f/DougHellmann?i=LsCWzi" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.doughellmann.com/~r/DougHellmann/~4/317534614" height="1" width="1"/&gt;</content><link rel="alternate" type="text/html" href="http://feeds.doughellmann.com/~r/DougHellmann/~3/317534614/svnbackup-news.html" title="svnbackup news" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=5440028356946346379&amp;postID=2636134930545720461" title="0 Comments" /><link rel="replies" type="application/atom+xml" href="http://blog.doughellmann.com/feeds/2636134930545720461/comments/default" title="Post Comments" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/5440028356946346379/posts/default/2636134930545720461" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/5440028356946346379/posts/default/2636134930545720461" /><author><name>Doug Hellmann</name><uri>http://www.blogger.com/profile/01892352754222143463</uri><email>noreply@blogger.com</email></author><feedburner:origLink>http://blog.doughellmann.com/2008/06/svnbackup-news.html</feedburner:origLink></entry><entry><id>tag:b