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

<channel>
	<title>Intrepid Blog &#187; python</title>
	<atom:link href="http://blog.affien.com/archives/tag/python/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.affien.com</link>
	<description>A few thoughts</description>
	<lastBuildDate>Mon, 01 Mar 2010 00:58:01 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Unicode to ASCII (1)</title>
		<link>http://blog.affien.com/archives/2009/06/19/unicode-to-ascii-1/</link>
		<comments>http://blog.affien.com/archives/2009/06/19/unicode-to-ascii-1/#comments</comments>
		<pubDate>Fri, 19 Jun 2009 13:19:10 +0000</pubDate>
		<dc:creator>Bas Westerbaan</dc:creator>
				<category><![CDATA[General]]></category>
		<category><![CDATA[hack]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[unicode]]></category>

		<guid isPermaLink="false">http://blog.affien.com/?p=387</guid>
		<description><![CDATA[When I want to generate usernames from real names, which can contain non-ascii characters, you can&#8217;t simply ignore the unicode characters.  For instance, danielle@blaat.org is the right e-mail address for Daniëlle, danille@blaat.org isn&#8217;t.
There&#8217;s  trick.  Unicode has got a single code for ë itself, but it has also got a code which (simplified) [...]]]></description>
			<content:encoded><![CDATA[<p>When I want to generate usernames from real names, which can contain non-ascii characters, you can&#8217;t simply ignore the unicode characters.  For instance, danielle@blaat.org is the right e-mail address for Daniëlle, danille@blaat.org isn&#8217;t.</p>
<p>There&#8217;s  trick.  Unicode has got a single code for ë itself, but it has also got a code which (simplified) adds ¨ on top of the previous character.  The unicode standard defines a normal form in which (at least) all such characters, which can be, are represented using such modifiers.  If you then simply ignore the non-ascii representable codes, you&#8217;ll get the desired result.</p>
<p>In python: <code>unicodedata.normalize('NFKD', txt).encode('ASCII', 'ignore')</code>.</p>
<p>However, this isn&#8217;t <em>the</em> right solution. For instance, in german, one prefers ue as a replacement of ü over u.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.affien.com/archives/2009/06/19/unicode-to-ascii-1/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>GStreamer: accurate duration</title>
		<link>http://blog.affien.com/archives/2009/04/19/gstreamer-accurate-duration/</link>
		<comments>http://blog.affien.com/archives/2009/04/19/gstreamer-accurate-duration/#comments</comments>
		<pubDate>Sun, 19 Apr 2009 13:26:01 +0000</pubDate>
		<dc:creator>Bas Westerbaan</dc:creator>
				<category><![CDATA[Computer Science]]></category>
		<category><![CDATA[duration]]></category>
		<category><![CDATA[gstreamer]]></category>
		<category><![CDATA[hack]]></category>
		<category><![CDATA[python]]></category>

		<guid isPermaLink="false">http://blog.affien.com/?p=371</guid>
		<description><![CDATA[When decoding, for instance, a variable-bitrate MP3, gstreamer reported durations are, to say the least, estimates.  I&#8217;ve tried to get a better result in a few ways.  First off, some files yield a duration tag, but even if you&#8217;re lucky and it is there, there are no guaranties about precision.  After that [...]]]></description>
			<content:encoded><![CDATA[<p>When decoding, for instance, a variable-bitrate MP3, gstreamer reported durations are, to say the least, estimates.  I&#8217;ve tried to get a better result in a few ways.  First off, some files yield a <code>duration</code> tag, but even if you&#8217;re lucky and it is there, there are no guaranties about precision.  After that I tried seeking to the end (<code>GST_SEEK_END</code>) of the stream and querying the position, which gstreamer didn&#8217;t like.  Finally, routing the audio into a <code>fakesink</code>, waiting for the end of stream and then querying for the position gives the right result.  It&#8217;s not the prettiest method, but it works.</p>
<p><a href='http://blog.affien.com/wp-content/uploads/2009/04/gst-duration.py'>This</a> is a Python script that prints the duration of a media to stdout.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.affien.com/archives/2009/04/19/gstreamer-accurate-duration/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>PyX</title>
		<link>http://blog.affien.com/archives/2008/07/08/pyx/</link>
		<comments>http://blog.affien.com/archives/2008/07/08/pyx/#comments</comments>
		<pubDate>Tue, 08 Jul 2008 00:57:56 +0000</pubDate>
		<dc:creator>Bas Westerbaan</dc:creator>
				<category><![CDATA[General]]></category>
		<category><![CDATA[graph]]></category>
		<category><![CDATA[LaTeX]]></category>
		<category><![CDATA[python]]></category>

		<guid isPermaLink="false">http://blog.w-nz.com/?p=321</guid>
		<description><![CDATA[The software I use to render those great graphs might be of interest to some.  Instead of using a clumsy GUI or an inflexible graph language, I use a Python library called PyX which is able to generate beautiful graphs.  At its core it&#8217;s a generator for TeX, and rendering graphs is just [...]]]></description>
			<content:encoded><![CDATA[<p>The software I use to render <a href="http://blog.w-nz.com/archives/2008/04/02/benchmarking-couchdb-1/">those</a> <a href="http://blog.w-nz.com/archives/2008/04/15/benchmarking-couchdb-2/">great</a> <a href="http://blog.w-nz.com/archives/2008/07/08/gits-versus-svns-storage-efficiency/">graphs</a> might be of interest to some.  Instead of using a clumsy GUI or an inflexible graph language, I use a Python library called <a href="http://pyx.sourceforge.net/">PyX</a> which is able to generate beautiful graphs.  At its core it&#8217;s a generator for TeX, and rendering graphs is just one thing it does well!</p>
<p>Take a look at the <a href="http://pyx.sourceforge.net/examples/index.html">examples</a> and convince yourself!</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.affien.com/archives/2008/07/08/pyx/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Benchmarking CouchDB (1)</title>
		<link>http://blog.affien.com/archives/2008/04/02/benchmarking-couchdb-1/</link>
		<comments>http://blog.affien.com/archives/2008/04/02/benchmarking-couchdb-1/#comments</comments>
		<pubDate>Wed, 02 Apr 2008 12:48:31 +0000</pubDate>
		<dc:creator>Bas Westerbaan</dc:creator>
				<category><![CDATA[General]]></category>
		<category><![CDATA[benchmark]]></category>
		<category><![CDATA[couchdb]]></category>
		<category><![CDATA[python]]></category>

		<guid isPermaLink="false">http://blog.w-nz.com/?p=305</guid>
		<description><![CDATA[I&#8217;ve written a small benchmark for couchdb to test it&#8217;s document creation performance.  A script creates  documents in total using bulk update to create  at the same time with  concurrent threads. The following graph show the time it takes to create an amount of documents against that amount of document for [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve written a small benchmark for couchdb to test it&#8217;s document creation performance.  A script creates <img src='/wp-latexrender/pictures/f9c4988898e7f532b9f826a75014ed3c.png' title='$N$' alt='$N$' align=absmiddle> documents in total using bulk update to create <img src='/wp-latexrender/pictures/61e84f854bc6258d4108d08d4c4a0852.png' title='$B$' alt='$B$' align=absmiddle> at the same time with <img src='/wp-latexrender/pictures/2f118ee06d05f3c2d98361d9c30e38ce.png' title='$T$' alt='$T$' align=absmiddle> concurrent threads. The following graph show the time it takes to create an amount of documents against that amount of document for different values of <img src='/wp-latexrender/pictures/61e84f854bc6258d4108d08d4c4a0852.png' title='$B$' alt='$B$' align=absmiddle> with <img src='/wp-latexrender/pictures/804c70e2e7d042c95b3a2995ad967adf.png' title='$T=1$' alt='$T=1$' align=absmiddle>.</p>
<p><a href='http://blog.w-nz.com/wp-content/uploads/2008/04/couchdb-create-t1.png'><img src="http://blog.w-nz.com/wp-content/uploads/2008/04/couchdb-create-t1.png" alt="" title="couchdb-create-t1" width="428" height="278" class="aligncenter size-full wp-image-306" /></a></p>
<p>And for <img src='/wp-latexrender/pictures/2cc82c99a866ae9891a91659fe42a57a.png' title='$T=2' alt='$T=2' align=absmiddle> (two concurrent threads.  Tested on a dual core machine)<br />
<a href='http://blog.w-nz.com/wp-content/uploads/2008/04/couchdb-create-t2.png'><img src="http://blog.w-nz.com/wp-content/uploads/2008/04/couchdb-create-t2.png" alt="" title="couchdb-create-t2" width="428" height="278" class="aligncenter size-full wp-image-307" /></a><br />
<small>The values of B are 1, 2, 4, 5, 8, 11, 16, 22, 32, 45, 64, 90, 128, 181, 256, 362, 512, 724 and 1024</small></p>
<p>As you can see, a higher value of <img src='/wp-latexrender/pictures/61e84f854bc6258d4108d08d4c4a0852.png' title='$B$' alt='$B$' align=absmiddle> causes the graph to shift to the right which means more <img src='/wp-latexrender/pictures/e25ec8b0af895735d0fe10be2ae08fc9.png' title='$N' alt='$N' align=absmiddle> for the same time.  Bulk update really does make a difference.  <em>Or</em> non-bulk-update really sucks.  Also adding threads does help a bit, but not as much as expected.</p>
<p>There are some more interesting graphs to plot (<img src='/wp-latexrender/pictures/61e84f854bc6258d4108d08d4c4a0852.png' title='$B$' alt='$B$' align=absmiddle> against <img src='/wp-latexrender/pictures/c412ce2392f725bea19da9b3385e1b4b.png' title='$\overline {N \over \Delta T} $' alt='$\overline {N \over \Delta T} $' align=absmiddle>).  More graphs tomorrow.</p>
<p>(For those interested, the <a href='http://blog.w-nz.com/wp-content/uploads/2008/04/results'>raw data</a> from which these graphs were plotted.)</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.affien.com/archives/2008/04/02/benchmarking-couchdb-1/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>CouchDB document creation performance</title>
		<link>http://blog.affien.com/archives/2008/03/30/couchdb-document-creation-performance/</link>
		<comments>http://blog.affien.com/archives/2008/03/30/couchdb-document-creation-performance/#comments</comments>
		<pubDate>Sat, 29 Mar 2008 23:24:10 +0000</pubDate>
		<dc:creator>Bas Westerbaan</dc:creator>
				<category><![CDATA[General]]></category>
		<category><![CDATA[benchmark]]></category>
		<category><![CDATA[couchdb]]></category>
		<category><![CDATA[python]]></category>

		<guid isPermaLink="false">http://blog.w-nz.com/?p=302</guid>
		<description><![CDATA[CouchDB is a non-relational database which uses MapReduce inspired views to query data.  There are lots of cool things to tell about its design, but I rather want to talk about its performance.
Today I&#8217;ve been busy hacking together a little script to import all e-mails of a long e-mail thread into a couchdb database [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://couchdb.org">CouchDB</a> is a non-relational database which uses <a href="http://labs.google.com/papers/mapreduce.html">MapReduce</a> inspired views to query data.  There are lots of cool things to tell about its design, but I rather want to talk about its performance.</p>
<p>Today I&#8217;ve been busy hacking together a little script to import all e-mails of a long e-mail thread into a couchdb database to write views to extract all kinds of statistics.  I already imported these e-mails into a MySQL database a few months ago, but was quite disappointed by the (performance) limitations of SQL.  The e-mail thread contains over 20,000 messages which weren&#8217;t a real problem for MySQL.  When importing, however, couchdb was adding them at a rate of only a few dozen per second with a lot of (seek)noise of my HDD.</p>
<p>So I decided to do a simple benchmark.  First of, a simple script (<a href='http://blog.w-nz.com/wp-content/uploads/2008/03/ser.py'>ser.py</a>) that adds empty documents sequentially.  It&#8217;s averaging 16 per second.  It occurred to me that couchdb waits for a <code>fsync</code> before sending a response and that asynchronously the performance would be way better. A simple modification to the script later (<a href='http://blog.w-nz.com/wp-content/uploads/2008/03/par.py'>par.py</a>) it still averaged 16 creations per second. </p>
<p>I guess, for I haven&#8217;t yet figured out how to let <code>strace</code>s tell me, that it&#8217;s the <code>fsync</code> after each object creation which causes the mess.  couchdb itself doesn&#8217;t write or seek a lot, but my <em>journaling</em> filesystem (XFS) does on a <code>fsync</code>.</p>
<p>Can anyone test it on a different filesystem?</p>
<p><ins>Update</ins> Around 17/sec with <code>reiserfs</code>. </p>
<p><ins>Update</ins> I had some trouble with the bulk update feature.  I switched from svn to the 0.7.2 release.  I got about 600/sec, which dropped to a steady-ish 350/sec when using sequential bulkupdates of 100 docs. Two bulk updates in parallel yield about 950/sec initially, dropping to 550/sec after a while.   Three parallel updates yield similar performance.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.affien.com/archives/2008/03/30/couchdb-document-creation-performance/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Tickle</title>
		<link>http://blog.affien.com/archives/2007/12/28/tickle/</link>
		<comments>http://blog.affien.com/archives/2007/12/28/tickle/#comments</comments>
		<pubDate>Fri, 28 Dec 2007 17:34:15 +0000</pubDate>
		<dc:creator>Bas Westerbaan</dc:creator>
				<category><![CDATA[General]]></category>
		<category><![CDATA[marietje]]></category>
		<category><![CDATA[pickle]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[serialization]]></category>
		<category><![CDATA[tickle]]></category>

		<guid isPermaLink="false">http://blog.w-nz.com/archives/2007/12/28/tickle/</guid>
		<description><![CDATA[Tickle is a small Python serializer like Pickle.  It however aims at generating smaller output:
&#62;&#62;&#62; len(tickle('hello'))
7
&#62;&#62;&#62; s = StringIO.StringIO()
&#62;&#62;&#62; pickle.dump('hello', s)
&#62;&#62;&#62; len(s.getvalue())
13
Though the difference is and remains quite small, this alone is useful for serialization of small things in the case of for instance RPC. However, usually you already know what kind of data [...]]]></description>
			<content:encoded><![CDATA[<p>Tickle is a small Python serializer like <a href="http://docs.python.org/lib/module-pickle.html">Pickle</a>.  It however aims at generating smaller output:</p>
<blockquote><p><code>&gt;&gt;&gt; len(tickle('hello'))<br />
7<br />
&gt;&gt;&gt; s = StringIO.StringIO()<br />
&gt;&gt;&gt; pickle.dump('hello', s)<br />
&gt;&gt;&gt; len(s.getvalue())<br />
13</code></p></blockquote>
<p>Though the difference is and remains quite small, this alone is useful for serialization of small things in the case of for instance RPC. However, usually you already know what kind of data to expect and you don&#8217;t really bother about the type information.  This can be done by specifying a template:</p>
<blockquote><p><code>&gt;&gt;&gt; obj = []<br />
&gt;&gt;&gt; for i in xrange(100):<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;obj.append((i, str(i)))<br />
&gt;&gt;&gt; len(tickle(obj))<br />
629<br />
&gt;&gt;&gt; len(tickle(obj, template=(tuple, \<br />
&nbsp;&nbsp;&nbsp;((tuple,((int,), (str,))),)*100)))<br />
390</code></p></blockquote>
<p>(Instead the *100 an iterator could be constructed, but that would clutter the example even more than it already is.) In comparison:</p>
<blockquote><p><code>&gt;&gt;&gt; s = StringIO.StringIO(); pickle.dump(obj, s)<br />
&gt;&gt;&gt; len(s.getvalue())<br />
1680</code></p></blockquote>
<p>One big disadvantage of Tickle is speed.  Pickle has got a nice C implementation, which is quite fast.  <a href="http://psyco.sourceforge.net/">Psyco</a> helps a bit but not really enough for really big things.  Even more so pickle is a bit smarter: it builds a LUT for instances to avoid duplicate data.  However, in the situations where Tickle will be used (by me at least) that isn&#8217;t too big of an issue.</p>
<p>You can download <a href="http://w-nz.com/gitweb/gitweb.cgi?p=marietje.git;a=blob_plain;f=tickle/tickle.py;hb=master">tickle.py</a> via <a href="http://w-nz.com/gitweb/gitweb.cgi">gitweb</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.affien.com/archives/2007/12/28/tickle/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>Virtual packages in python</title>
		<link>http://blog.affien.com/archives/2007/11/10/virtual-packages-in-python/</link>
		<comments>http://blog.affien.com/archives/2007/11/10/virtual-packages-in-python/#comments</comments>
		<pubDate>Sat, 10 Nov 2007 21:11:07 +0000</pubDate>
		<dc:creator>Bas Westerbaan</dc:creator>
				<category><![CDATA[General]]></category>
		<category><![CDATA[package]]></category>
		<category><![CDATA[python]]></category>

		<guid isPermaLink="false">http://blog.w-nz.com/archives/2007/11/10/virtual-packages-in-python/</guid>
		<description><![CDATA[When writing an application in python, it can be very convenient to be able to import a module from the top of your module tree.  Eg. import myapp.config instead of (python 2.5 only) relative imports: import ....config. To do this one would have to make myapp a package.  The normal way to do [...]]]></description>
			<content:encoded><![CDATA[<p>When writing an application in python, it can be very convenient to be able to import a module from the top of your module tree.  Eg. <code>import myapp.config</code> instead of (python 2.5 only) relative imports: <code>import ....config</code>. To do this one would have to make <code>myapp</code> a package.  The normal way to do this is to put your application directory (which now has to be named <code>myapp</code>) somewhere in python&#8217;s package search path.  This isn&#8217;t all to convenient.</p>
<p>The solution: manually set up your package module:</p>
<p><code>import os<br />
import sys<br />
import imp<br />
def setup_virtual_package(name, path=os.curdir):<br />
&nbsp;&nbsp;&nbsp;&nbsp;&quot;&quot;&quot; Sets up a package at the given path with a given<br />
&nbsp;&nbsp;&nbsp;&nbsp;        name &quot;&quot;&quot;<br />
&nbsp;&nbsp;&nbsp;&nbsp;modulePath = os.path.abspath(path)<br />
&nbsp;&nbsp;&nbsp;&nbsp;f, fn, suffix = imp.find_module('__init__', <br />
&nbsp;&nbsp;&nbsp;&nbsp;                                &nbsp;&nbsp;&nbsp;&nbsp;[modulePath])<br />
&nbsp;&nbsp;&nbsp;&nbsp;imp.load_module(name, f, fn, suffix)<br />
&nbsp;&nbsp;&nbsp;&nbsp;sys.modules[name].__path__ = [modulePath]</code></p>
<p>Now <code>import myapp.something</code> works like a charm.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.affien.com/archives/2007/11/10/virtual-packages-in-python/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Virtual package for your python application</title>
		<link>http://blog.affien.com/archives/2007/04/21/virtual-package-for-your-python-application/</link>
		<comments>http://blog.affien.com/archives/2007/04/21/virtual-package-for-your-python-application/#comments</comments>
		<pubDate>Sat, 21 Apr 2007 18:45:06 +0000</pubDate>
		<dc:creator>Bas Westerbaan</dc:creator>
				<category><![CDATA[Code sniplets]]></category>
		<category><![CDATA[Computer Science]]></category>
		<category><![CDATA[package]]></category>
		<category><![CDATA[python]]></category>

		<guid isPermaLink="false">http://blog.w-nz.com/archives/2007/04/21/virtual-package-for-your-python-application/</guid>
		<description><![CDATA[When you&#8217;ve got a big python application, you&#8217;ll usually split it up in modules.  One big annoyance I&#8217;ve had is that a module inside a directory cannot (easily) import a module higher up in the tree. Eg: drawers/gtk.py cannot import state/bla.py.
This is usually solved by making the application a package. This allows for import [...]]]></description>
			<content:encoded><![CDATA[<p>When you&#8217;ve got a big python application, you&#8217;ll usually split it up in modules.  One big annoyance I&#8217;ve had is that a module inside a directory cannot (easily) import a module higher up in the tree. Eg: drawers/gtk.py cannot import state/bla.py.</p>
<p>This is usually solved by making the application a package. This allows for <code>import myapp.drawers.gtk</code> from everywhere inside your application. To make it a package though, you need to add the parent directory in the <code>sys.path</code> list.  But unfortunately this also includes all other subdirectories of the parent directory as packages.</p>
<p>However, when the package module (eg: <code>myapp</code>) was already loaded, then the path from which <code>myapp</code> was loaded is used to find the submodules (eg: <code>myapp.drawers.gtk</code>) and <code>sys.path</code> isn&#8217;t looked at, at all. So, here is the trick:</p>
<pre>import sys
import os.path

p = os.path.dirname(__file__)
sys.path.append(os.path.abspath(p+"/.."))
__import__(os.path.basename(p))
sys.path.pop()</pre>
<p>Note that this script doesn&#8217;t work when directly executed, because the <code>__file__</code> attribute is only available when loaded as a module.</p>
<p>Save this script as <code>loader.py</code> in the root of your application. <code>import loader</code> from the main script in your app, and you&#8217;ll be able to import modules by <code>myapp.a.module</code>, where <code>myapp</code> is the root directory name of your application.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.affien.com/archives/2007/04/21/virtual-package-for-your-python-application/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Python Imaging Library</title>
		<link>http://blog.affien.com/archives/2007/01/30/python-imaging-library/</link>
		<comments>http://blog.affien.com/archives/2007/01/30/python-imaging-library/#comments</comments>
		<pubDate>Mon, 29 Jan 2007 23:54:39 +0000</pubDate>
		<dc:creator>Bas Westerbaan</dc:creator>
				<category><![CDATA[useless]]></category>
		<category><![CDATA[pil]]></category>
		<category><![CDATA[python]]></category>

		<guid isPermaLink="false">http://blog.w-nz.com/archives/2007/01/30/python-imaging-library/</guid>
		<description><![CDATA[PIL is great. In less than a thousand lines one can compute the polygons from regions, assess the best possible subimage layout and create all the subimages.

]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.pythonware.com/library/pil/">PIL</a> is great. In less than a thousand lines one can compute the polygons from regions, assess the best possible subimage layout and create all the subimages.<br />
<a class="imagelink" href="http://blog.w-nz.com/wp-content/uploads/2007/01/npar3.png" title="npar3.png"><img id="image237" src="http://blog.w-nz.com/wp-content/uploads/2007/01/npar3.thumbnail.png" alt="npar3.png" /></a></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.affien.com/archives/2007/01/30/python-imaging-library/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Python Url Encoding</title>
		<link>http://blog.affien.com/archives/2005/06/25/python-url-encoding/</link>
		<comments>http://blog.affien.com/archives/2005/06/25/python-url-encoding/#comments</comments>
		<pubDate>Fri, 24 Jun 2005 23:00:20 +0000</pubDate>
		<dc:creator>Bas Westerbaan</dc:creator>
				<category><![CDATA[Code sniplets]]></category>
		<category><![CDATA[encodng]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[url]]></category>

		<guid isPermaLink="false">http://blog.w-nz.com/?p=102</guid>
		<description><![CDATA[I looked in the Python Library Reference for a function to encode special characters in strings to be able to be put in Urls (and Uri&#8217;s), but found none.
Maybe I missed it?
Anyways, here is an implementation I wrote based on this article:
HexCharacters = &#34;0123456789abcdef&#34;

def UrlEncode(s):
    r = ''
    for [...]]]></description>
			<content:encoded><![CDATA[<p>I looked in the <a href="http://docs.python.org/lib/lib.html">Python Library Reference</a> for a function to encode special characters in strings to be able to be put in Urls (and Uri&#8217;s), but found none.</p>
<p>Maybe I missed it?</p>
<p>Anyways, here is an implementation I wrote based on <a href="http://www.blooberry.com/indexdot/html/topics/urlencoding.htm">this article</a>:</p>
<blockquote><pre style='font-size:larger;'>HexCharacters = &quot;0123456789abcdef&quot;

def UrlEncode(s):
    r = ''
    for c in s:
        o = ord(c)
        if (o &gt;= 48 and o &lt;= 57) or \
            (o &gt;= 97 and o &lt;= 122) or \
            (o &gt;= 65 and o &lt;= 90) or \
            o == 36 or o == 45 or o == 95 or \
            o == 46 or o == 43 or o == 33 or \
            o == 42 or o == 39 or o == 40 or \
            o == 41 or o == 44:
            r += c
        else:
            r += '%' + CleanCharHex(c)
    return r

def CleanCharHex(c):
    o = ord(c)
    r = HexCharacters[o / 16]
    r += HexCharacters[o % 16]
    return r</pre>
</blockquote>
<p>note: I used the character numbers instead the characters to compare with so I could do greater than and lesser than for the alphanumeric numbers. Maybe testing with a bitmask would be more efficient.</p>
<p>I have to write almost everytime I work with python my own <em>something to hex</em> function which doesn&#8217;t add the &#8216;0x&#8217; in front the built-in <em>hex</em> does.</p>
<p>Either I can&#8217;t search or Python hasn&#8217;t got enough batteries included. I guess the first, if not I`ll submit my batteries.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.affien.com/archives/2005/06/25/python-url-encoding/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
	</channel>
</rss>
