<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
<channel>
  <link>http://mikewatkins.ca/tags/python/</link>
  <atom:link href="http://mikewatkins.ca/tags/python/feeds/rss" type="application/rss+xml" rel="self"/>
  <lastBuildDate>Thu, 17 Mar 2011 20:24:12 GMT</lastBuildDate>
  <title>mike watkins dot ca</title>
  <description>XML Feed for mike watkins dot ca</description>
  <language>en</language>
  <generator>Parlez/0.1</generator>
<item>
  <title>Japan Nuclear Status Feed</title>
  <link>http://mikewatkins.ca/2011/03/17/japan-nuclear-status-feed/</link>
  <description><![CDATA[
<div class="document">
<p>For the duration of the nuclear crisis in Japan I'm producing a XML (Atom) feed of the status reports published by the <a class="reference external" href="http://www.jaif.or.jp/english/">Japan Atomic Industrial Forum Inc.</a> (JAIF) The JAIF site is checked every 10 minutes for updates; they seem to be updating a couple times per day.</p>
<p><strong>News readers can subscribe to the feed at:</strong> <a class="reference external" href="http://mikewatkins.ca/japan_status.xml">http://mikewatkins.ca/japan_status.xml</a></p>
<p>Now included in the same feed are any post-earthquake updates from <a class="reference external" href="http://www.tepco.co.jp/en/press/corp-com/release/index-e.html">Tokyo Electric Power Company</a> (TEPCO). In addition the feed includes earthquake reports from the <a class="reference external" href="http://earthquake.usgs.gov/earthquakes/catalogs/">U.S. Geological Survey</a>, limited to  earthquakes near Japan, Hawaii, Canada and the U.S. west coast - with a magnitude of 5.4 or greater.</p>
<p>The International Atomic Energy Agency is maintaining a <a class="reference external" href="http://www.iaea.org/newscenter/news/tsunamiupdate01.html">daily update log</a>.</p>
<p>Another compiled source of information on the disaster is available from <a class="reference external" href="http://nirs.org/">http://nirs.org/</a> - organized chronologically, <a class="reference external" href="http://www.nirs.org/reactorwatch/accidents/Fukushimafactsheet.pdf">this PDF may be of interest</a>.</p>
<div class="note">
<p class="first admonition-title">Note</p>
<p class="last">The feed is produced using <a class="reference external" href="http://python.org/">Python</a> and <a class="reference external" href="http://lxml.de/">lxml</a> to both parse the original HTML and construct an Atom tree and serialize it to an XML file (which now <a class="reference external" href="http://feedvalidator.org/check.cgi?url=http%3A%2F%2Fmikewatkins.ca%2Fjapan_status.xml">validates as Atom</a> unlike the first cut!).</p>
</div>
</div>

]]></description>
  <guid isPermaLink="false">tag:mikewatkins.ca,2007-10-10:journal:mw:entry:798</guid>
  <pubDate>Thu, 17 Mar 2011 20:24:12 GMT</pubDate>
  <category>disaster</category>
  <category>japan</category>
  <category>nuclear</category>
  <category>python</category>
</item>
<item>
  <title>Python Object Persistence</title>
  <link>http://mikewatkins.ca/2010/06/17/python-object-persistence/</link>
  <description><![CDATA[
<div class="document">
<p>Noted via #python on Twitter, a link to <a class="reference external" href="http://www.mentby.com/Group/python-tutor/how-to-model-objects-aimed-to-persistence.html">this discussion</a> on creating a simple Movie and Actor database. Some suggestions for the original poster included using Shelve; myself I'd prefer to move up a rung or two and use a Python object database like <a class="reference external" href="http://www.zodb.org/">ZODB</a> or <a class="reference external" href="http://www.mems-exchange.org/software/durus/">Durus</a>, either of which can be used for anything from simple to complex solutions.</p>
<p>Attached is a dirt-simple module implementing a movie and actor database. Look ma, no SQL. The core of it is here, with the objects of interest subclassing Durus's Persistent class:</p>
<div class="highlight"><pre><span class="c"># Our &quot;Models&quot; -- it&#39;s just Python.</span>

<span class="k">class</span> <span class="nc">Actor</span><span class="p">(</span><span class="n">Persistent</span><span class="p">):</span>

    <span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">name</span><span class="p">):</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">name</span> <span class="o">=</span> <span class="n">name</span>

    <span class="k">def</span> <span class="nf">__str__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="k">return</span> <span class="s">&#39;&lt;Actor: </span><span class="si">%s</span><span class="s">&gt;&#39;</span> <span class="o">%</span> <span class="bp">self</span><span class="o">.</span><span class="n">name</span>


<span class="k">class</span> <span class="nc">Movie</span><span class="p">(</span><span class="n">Persistent</span><span class="p">):</span>

    <span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">title</span><span class="p">):</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">title</span> <span class="o">=</span> <span class="n">title</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">actors</span> <span class="o">=</span> <span class="n">PersistentSet</span><span class="p">()</span>

    <span class="k">def</span> <span class="nf">add_actor</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">actor</span><span class="p">):</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">actors</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="n">actor</span><span class="p">)</span>

    <span class="k">def</span> <span class="nf">__str__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="k">return</span> <span class="s">&#39;&lt;Movie: </span><span class="si">%s</span><span class="s">&gt;&#39;</span> <span class="o">%</span> <span class="bp">self</span><span class="o">.</span><span class="n">title</span>


<span class="k">class</span> <span class="nc">Database</span><span class="p">(</span><span class="n">Persistent</span><span class="p">):</span>

    <span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">movies</span> <span class="o">=</span> <span class="n">PersistentDict</span><span class="p">()</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">actors</span> <span class="o">=</span> <span class="n">PersistentDict</span><span class="p">()</span>

    <span class="k">def</span> <span class="nf">add_movie</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">movie</span><span class="p">):</span>
        <span class="k">assert</span> <span class="n">movie</span><span class="o">.</span><span class="n">title</span> <span class="ow">not</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">movies</span><span class="p">,</span> <span class="s">&#39;Already exists!&#39;</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">movies</span><span class="p">[</span><span class="n">movie</span><span class="o">.</span><span class="n">title</span><span class="p">]</span> <span class="o">=</span> <span class="n">movie</span>
        <span class="k">return</span> <span class="n">movie</span>

    <span class="k">def</span> <span class="nf">get_movie</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">title</span><span class="p">):</span>
        <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">movies</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">title</span><span class="p">,</span> <span class="bp">None</span><span class="p">)</span>

    <span class="k">def</span> <span class="nf">add_actor</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">actor</span><span class="p">):</span>
        <span class="k">assert</span> <span class="n">actor</span><span class="o">.</span><span class="n">name</span> <span class="ow">not</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">actors</span><span class="p">,</span> <span class="s">&#39;Already exists!&#39;</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">actors</span><span class="p">[</span><span class="n">actor</span><span class="o">.</span><span class="n">name</span><span class="p">]</span> <span class="o">=</span> <span class="n">actor</span>

    <span class="k">def</span> <span class="nf">get_actor</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">name</span><span class="p">):</span>
        <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">actors</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">name</span><span class="p">,</span> <span class="bp">None</span><span class="p">)</span>

    <span class="k">def</span> <span class="nf">appears_in</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">actor</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;(actor : Actor) -&gt; [Movie,]</span>

<span class="sd">        Returns a sequence of Movies, if any, the Actor played a role in.</span>
<span class="sd">        &quot;&quot;&quot;</span>
        <span class="k">return</span> <span class="p">[</span><span class="n">m</span> <span class="k">for</span> <span class="n">m</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">movies</span><span class="o">.</span><span class="n">values</span><span class="p">()</span> <span class="k">if</span> <span class="n">actor</span> <span class="ow">in</span> <span class="n">m</span><span class="o">.</span><span class="n">actors</span><span class="p">]</span>
</pre></div>
<p>Objects which subclass the Persistent class become persistence-aware. Aside from having some special <em>container</em> classes for persistent dicts, lists, sets and BTrees for performance with large mappings, there isn't much of a mental burden to design objects that participate in a Durus or ZODB object database.</p>
<p>An example of retrieving some data from our film database:</p>
<div class="highlight"><pre><span class="k">if</span> <span class="n">__name__</span> <span class="o">==</span> <span class="s">&#39;__main__&#39;</span><span class="p">:</span>
    <span class="kn">from</span> <span class="nn">examples.durus.flicks.movies</span> <span class="kn">import</span> <span class="n">load_it</span><span class="p">,</span> <span class="n">get_db</span>
    <span class="kn">from</span> <span class="nn">durus.file_storage</span> <span class="kn">import</span> <span class="n">FileStorage</span>
    <span class="kn">from</span> <span class="nn">durus.connection</span> <span class="kn">import</span> <span class="n">Connection</span>

    <span class="n">connection</span> <span class="o">=</span> <span class="n">Connection</span><span class="p">(</span><span class="n">FileStorage</span><span class="p">(</span><span class="s">&quot;movies.durus&quot;</span><span class="p">))</span>
    <span class="c"># load some sample data</span>
    <span class="k">if</span> <span class="ow">not</span> <span class="n">connection</span><span class="o">.</span><span class="n">get_root</span><span class="p">()</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s">&#39;films&#39;</span><span class="p">,</span> <span class="bp">False</span><span class="p">):</span>
        <span class="n">load_it</span><span class="p">(</span><span class="n">connection</span><span class="p">)</span>
    <span class="n">db</span> <span class="o">=</span> <span class="n">get_db</span><span class="p">(</span><span class="n">connection</span><span class="p">)</span>
    <span class="n">hopkins</span> <span class="o">=</span> <span class="n">db</span><span class="o">.</span><span class="n">get_actor</span><span class="p">(</span><span class="s">&#39;Anthony Hopkins&#39;</span><span class="p">)</span>
    <span class="n">mel</span> <span class="o">=</span> <span class="n">db</span><span class="o">.</span><span class="n">get_actor</span><span class="p">(</span><span class="s">&#39;Mel Gibson&#39;</span><span class="p">)</span>

    <span class="c"># Which films has an actor appeared in?</span>
    <span class="k">for</span> <span class="n">actor</span> <span class="ow">in</span> <span class="p">(</span><span class="n">hopkins</span><span class="p">,</span> <span class="n">mel</span><span class="p">):</span>
        <span class="k">print</span><span class="p">()</span>
        <span class="k">print</span><span class="p">(</span><span class="s">&#39;</span><span class="si">%s</span><span class="s"> is in:&#39;</span> <span class="o">%</span> <span class="n">actor</span><span class="o">.</span><span class="n">name</span><span class="p">)</span>
        <span class="k">print</span><span class="p">([</span><span class="nb">str</span><span class="p">(</span><span class="n">m</span><span class="p">)</span> <span class="k">for</span> <span class="n">m</span> <span class="ow">in</span> <span class="n">db</span><span class="o">.</span><span class="n">appears_in</span><span class="p">(</span><span class="n">actor</span><span class="p">)])</span>

    <span class="c"># What films are in our movie database and name known actors in each</span>
    <span class="k">print</span><span class="p">(</span><span class="s">&quot;</span><span class="se">\n</span><span class="s">Complete Movie Listing&quot;</span><span class="p">)</span>
    <span class="k">for</span> <span class="n">m</span> <span class="ow">in</span> <span class="n">db</span><span class="o">.</span><span class="n">movies</span><span class="o">.</span><span class="n">values</span><span class="p">():</span>
        <span class="k">print</span><span class="p">(</span><span class="n">m</span><span class="o">.</span><span class="n">title</span><span class="p">,</span> <span class="s">&#39;:&#39;</span><span class="p">,</span> <span class="s">&#39;,&#39;</span><span class="o">.</span><span class="n">join</span><span class="p">([</span><span class="nb">str</span><span class="p">(</span><span class="n">a</span><span class="p">)</span> <span class="k">for</span> <span class="n">a</span> <span class="ow">in</span> <span class="n">m</span><span class="o">.</span><span class="n">actors</span><span class="p">]))</span>
</pre></div>
<p>Running this script the first time you'll note some log activity to <cite>stdout</cite> as the object instances are committed to the database. The listing output will look like this:</p>
<pre class="literal-block">
Anthony Hopkins is in:
['&lt;Movie: Mutiny on the Bounty&gt;']

Mel Gibson is in:
['&lt;Movie: Braveheart&gt;', '&lt;Movie: Lethal Weapon II&gt;',
'&lt;Movie: Mutiny on the Bounty&gt;', '&lt;Movie: Lethal Weapon III&gt;',
'&lt;Movie: Lethal Weapon&gt;']

Complete Movie Listing
Braveheart : &lt;Actor: Mel Gibson&gt;
Lethal Weapon II : &lt;Actor: Mel Gibson&gt;,&lt;Actor: Danny Glover&gt;
Mutiny on the Bounty : &lt;Actor: Mel Gibson&gt;,&lt;Actor: Anthony Hopkins&gt;
Lethal Weapon III : &lt;Actor: Mel Gibson&gt;,&lt;Actor: Danny Glover&gt;
Lethal Weapon : &lt;Actor: Mel Gibson&gt;,&lt;Actor: Danny Glover&gt;
</pre>
<p><em>(No commentary on my taste for films, please)</em></p>
<p>In addition to the <tt class="docutils literal"><span class="pre">FileStorage</span></tt> class, Durus offers a client-server solution <tt class="docutils literal"><span class="pre">ClientStorage</span></tt> suitable for use by multi-process applications such as web apps. ZODB provides the same through its  ZEO feature.</p>
</div>

]]></description>
  <guid isPermaLink="false">tag:mikewatkins.ca,2007-10-10:journal:mw:entry:788</guid>
  <pubDate>Thu, 17 Jun 2010 07:02:11 GMT</pubDate>
  <category>python</category>
</item>
<item>
  <title>Easy Install, Often Isn&#39;t</title>
  <link>http://mikewatkins.ca/2010/05/15/easy-install-often-isnt/</link>
  <description><![CDATA[
<div class="document">
<p>I'm sure I'm not the only one who suffers from &quot;installation frustration&quot; from time to time. At the outset I want to declare that I'm not complaining about <tt class="docutils literal"><span class="pre">easy_install</span></tt> at all here. In fact, I'm not complaining about anything at all but instead am pointing out what a bad installation experience does to the curious.</p>
<p>My story is cyclical in nature. I don't do any Zope work but do work with ZODB and Durus, a ZODB work alike, and a web app traversal mechanism that is Zope-similar. As a result I'm always inclined to check out major new releases of Zope or Grok or Plone and the ecosystem that surrounds same.</p>
<p>Sadly I've learned to expect frustration and failure in pursuit of my goal to get the new tool of the day installed and have a quick peek at a running demonstration app and examine what's under the covers.</p>
<p>Yet as time passes and the frustration fades, invariably I find myself willing to try again, which brings us to the present. Plone 4 is moving through beta releases and today seemed like a good day to install it and peek under the covers. The official documentation is simple enough, but installation failed and left me with a hankering to cure the problem with <tt class="docutils literal"><span class="pre">rm</span> <span class="pre">-rf</span> <span class="pre">plone</span></tt>.</p>
<p>Later in the day, inspired by the Jazkarta Blog entry on <a class="reference external" href="http://blog.jazkarta.com/2010/05/15/installing-plone-without-buildout/?utm_source=feedburner&amp;utm_medium=feed&amp;utm_campaign=Feed:+JazkartaBlog+(Jazkarta+Blog)">easy_install Plone</a>, I thought I'd do just that give it another go. No joy there either, and the comments have since sprouted a warning that this should not be done, for well and good legitimate reasons.</p>
<p>But the bottom line remains that a <tt class="docutils literal"><span class="pre">buildout</span></tt> driven install plus official documentation failed to deliver a working instance, so what does one do? Roll out <tt class="docutils literal"><span class="pre">rm</span> <span class="pre">-rf</span> <span class="pre">plone</span></tt> and move on?</p>
<p>This sort of installation frustration isn't limited to major albeit often beta releases, and certainly isn't limited to Zope or Plone or Grok, although their very long chain of tools can make it daunting for a complete greenhorn to puzzle out a solution quickly. I've had the same experience same thing occur with official tutorials, or too often even basic installation documentation is simply wrong.</p>
<p>Remember, this isn't a complaint. I know how much effort goes into solution development and that many products are built largely or entirely on the back of volunteer labour. I'm merely pointing out that a bad installation experience can turn off someone who might otherwise be a relatively decent candidate to use the product and perhaps one day become part of the contributing community. Those who are on the outside of a product's community haven't yet drunk the koolaid and don't know what fantastic stuff is hidden within the bowels of your package, and they might never know, if the cost of admittance is too steep from the outset.</p>
<p>At the very least make sure the new release can install on a totally new system, or a clean <tt class="docutils literal"><span class="pre">virtualenv</span></tt>, by following only the installation instructions, followed verbatim, in your README or INSTALL files. Don't introduce jargon into these first documentation entry points that outsiders will not know.</p>
</div>

]]></description>
  <guid isPermaLink="false">tag:mikewatkins.ca,2007-10-10:journal:mw:entry:772</guid>
  <pubDate>Sat, 15 May 2010 22:35:43 GMT</pubDate>
  <category>python</category>
</item>
<item>
  <title>FreeBSD VPS</title>
  <link>http://mikewatkins.ca/2009/11/26/freebsd-vps/</link>
  <description><![CDATA[
<div class="document">
<p>Over the past nine months I've been leasing a <a class="reference external" href="http://freebsdvps.com/">FreeBSD VPS</a> (Virtual Private Server) to supplement my own hardware and I've just realized that the virtual machine hasn't caused me any (more) grey hair or other anguish in all that time.  In my books vendors that save hair and brain cells deserve at least a passing mention.</p>
<p>At present I'm using one FreeBSD VPS for staging Python web apps and hosting a couple of pro bono sites. I quite frequently refer people to more full-service shared hosting firms such as WebFaction (even my brother has an account there) but personally I prefer managing the entire box - virtual or not - myself.</p>
<p>As I'd like to turn off some aging servers of my own, I'm hoping that virtualization from firms like ARP Networks, or on grander scale like Google or Amazon's cloud services, will save me spending some funds on equipment leases. I've tried a few &quot;virtual&quot; server providers over the years but I do believe this is the first time I've passed on a recommendation here in these pages.</p>
<p>What I like:</p>
<ul class="simple">
<li>OS support: FreeBSD, OpenBSD, and most Linux distributions</li>
<li>Decent multi-homed bandwidth with redundancy and plenty of peering agreements turned up; data center is in LA; quite good network access to Asia, Australia</li>
<li>IPv6 support</li>
<li>IP accessible / out-of-band console access</li>
<li>Configure, build and install your own world and kernel if you like</li>
<li>Great performance, terrific even if you measure performance per dollar. I can churn out &gt; 1000 requests per second with a trivial test page with a single DB lookup, which is a darn sight better than some of my own ageing hardware is able to do.</li>
</ul>
<p>What I wish they offered:</p>
<ul class="simple">
<li>a Canadian datacenter too!</li>
</ul>
<p>The virtualization technology involves KVM (not Xen or OpenVZ) and I find that the resource allocation is very fair indeed. 768MB RAM / 20GB disk / 100GB bandwidth - all this and I get stability too for $20 USD a month.</p>
<p>There are plenty of really cheap virtual server offerings out there, but not very many stable yet inexpensive operations. ARP Networks is certainly one of the latter.</p>
<p>FreeBSDvps.com / <a class="reference external" href="http://OpenBSDvps.net/">OpenBSDvps.net</a> will both lead you to <a class="reference external" href="http://arpnetworks.com/vps">ARP Networks</a> which is the love child of Garry Dolley. Garry not only knows what he is doing, he actually appears to enjoy managing server and network hardware.</p>
<p>Everyone appreciates reliable hardware and networks, but I think the service offering will appeal most to those who can competently manage a server from the command line. ARP Networks' target market appears to be <em>people who know what they are doing</em>, which is good company to keep.</p>
</div>

]]></description>
  <guid isPermaLink="false">tag:mikewatkins.ca,2007-10-10:journal:mw:entry:749</guid>
  <pubDate>Thu, 26 Nov 2009 04:03:14 GMT</pubDate>
  <category>python</category>
  <category>technical</category>
</item>
<item>
  <title>QP and Durus Updated</title>
  <link>http://mikewatkins.ca/2009/08/25/qp-and-durus-updated/</link>
  <description><![CDATA[
<div class="document">
<p>The folks at <a class="reference external" href="http://www.mems-exchange.org/software/">mems-exchange.org</a> released a <a class="reference external" href="http://mail.mems-exchange.org/durusmail/qp/453/">new version of the Python web application / site-management framework QP</a> and supporting packages.</p>
<p>All of today's released packages support Python &gt;= 2.4, which includes Python 3.1.</p>
<p>They also released an <a class="reference external" href="http://mail.mems-exchange.org/durusmail/durus-users/989/">update to Durus</a>, a compact and mature Python object database (which at its core operates like a minimal ZODB/ZEO work-a-like). The API to a Python object db is simply Python.</p>
<p>Key-value databases appear to be in vogue these days. Python developers with an interest in key-value databases may want to check out Durus (or ZODB): the key-value database you already know, <em>and more</em>.</p>
<p><em>More</em> means more than key-value pairs and simple types. More means virtually any Python object / type. More means more than simple string or integer keys  and simple values and offers not only persistent dictionaries but also persistent lists and sets, and persistent objects of most any design you may wish to implement.</p>
<p>Durus has no other package dependencies and is compact. Weighing in with less than 5000 lines of code it small enough to read in one sitting if you want to see how things tick. Or <a class="reference external" href="http://www.mems-exchange.org/software/durus/Durus-3.9.tar.gz/Durus-3.9/README.txt">you can just dive in</a> - start a server <tt class="docutils literal"><span class="pre">durus</span> <span class="pre">-s</span></tt> and a client <tt class="docutils literal"><span class="pre">durus</span> <span class="pre">-c</span></tt> and play.</p>
</div>

]]></description>
  <guid isPermaLink="false">tag:mikewatkins.ca,2007-10-10:journal:mw:entry:715</guid>
  <pubDate>Tue, 25 Aug 2009 19:25:20 GMT</pubDate>
  <category>durus</category>
  <category>python</category>
  <category>qp</category>
</item>
<item>
  <title>Exploits Away</title>
  <link>http://mikewatkins.ca/2009/07/04/exploits-away/</link>
  <description><![CDATA[
<div class="document">
<p>Cold Fusion and some PHP sites are being hit hard over the last 24 hours by what appear to be Chinese cyber-criminals using an exploit found within the popular browser-based editor component <a class="reference external" href="http://www.fckeditor.net/">FCKeditor</a>. The vulnerability allows for remote code execution / uploading of files to arbitrary locations / installation of remote shells and it would appear that many sites are being attacked.</p>
<p>Versions &lt;= the current shipping version (FCKeditor &lt;= 2.6.4) are vulnerable. A patch does not yet exist; in the mean time disabling the file browser is one of the mitigation steps.</p>
<p>A number of Python projects utilize this editor component.</p>
<p>oCERT Advisory: <a class="reference external" href="http://www.ocert.org/advisories/ocert-2009-007.html">http://www.ocert.org/advisories/ocert-2009-007.html</a></p>
</div>

]]></description>
  <guid isPermaLink="false">tag:mikewatkins.ca,2007-10-10:journal:mw:entry:713</guid>
  <pubDate>Sat, 04 Jul 2009 16:36:57 GMT</pubDate>
  <category>python</category>
  <category>security</category>
</item>
<item>
  <title>New and Improved - Python 3.1</title>
  <link>http://mikewatkins.ca/2009/06/29/new-and-improved-python-31/</link>
  <description><![CDATA[
<div class="document">
<p><em>Updated to include a comparison to Python 2.5</em></p>
<p>Python 3.1 has closed much of the performance gap between 3.x and 2.x, as well as <a class="reference external" href="http://docs.python.org/3.1/whatsnew/3.1.html">delivering some new features and enhancements to the language and stdlib</a>. Enhancement that caught my eye first: <tt class="docutils literal"><span class="pre">re.sub</span> <span class="pre">|</span> <span class="pre">re.subn</span> <span class="pre">|</span> <span class="pre">re.split</span></tt> now accept a flags parameter, no more remembering how to pass that in as part of the regex. And I think I'm going to like auto numbered format() fields i.e. <tt class="docutils literal"><span class="pre">'We</span> <span class="pre">are</span> <span class="pre">the</span> <span class="pre">{}</span> <span class="pre">who</span> <span class="pre">say</span> <span class="pre">{}'.format('Knights',</span> <span class="pre">'Ni!')</span></tt>.</p>
<p>On first blush it may not seem that the performance gap has been closed very much. A simplistic web app benchmark:</p>
<pre class="literal-block">
siege -b -t60s -c2  http://localhost:8000/

Old machine (light mail server load / FreeBSD 7.2)
Python 2.6     520.91 trans/sec
Python 3.1     388.38 trans/sec

Newer Virtual Machine (moderately loaded server / FreeBSD 7.2)
Python 2.6   1568.58 trans/sec
Python 3.1    1220.92 trans/sec

Faster Virtual Machine (quiet server / Debian 5 - OpenVZ)
Python 2.5    2304.78 trans/sec [1]
Python 3.1    1960.07 trans/sec
</pre>
<p>Looking deeper, I'm seeing little difference between 2.6 and 3.1, here benchmarking a more involved web app benchmark than &quot;hello world&quot; that is probably more representative of a typical yet simple web app:</p>
<pre class="literal-block">
siege -b -t60s -c2  http://localhost:8002/

Old machine (light mail server load / FreeBSD 7.2)
Python 2.6    197.40 trans/sec
Python 3.1    194.09 trans/sec

Newer Virtual Machine (moderately loaded server / FreeBSD 7.2)
Python 2.6    649.57 trans/sec
Python 3.1    629.50 trans/sec

Faster Virtual Machine (quiet server / Debian 5 - OpenVZ)
Python 2.5    765.88 trans/sec
Python 3.1    850.24 trans/sec
</pre>
<p>[1] Note Python 2.5 being compared in this test instance</p>
<p>From what I can tell, for the sorts of tasks I run into,  Python 3.1 appears to perform as well or better than Python 2.5 and is approaching the current speed daemon, Python 2.6.  Take that with a grain of salt, as I found 3.0 was fast enough for my needs.</p>
</div>

]]></description>
  <guid isPermaLink="false">tag:mikewatkins.ca,2007-10-10:journal:mw:entry:712</guid>
  <pubDate>Mon, 29 Jun 2009 04:14:45 GMT</pubDate>
  <category>python</category>
</item>
<item>
  <title>It&#39;s Alive</title>
  <link>http://mikewatkins.ca/2009/06/14/its-alive/</link>
  <description><![CDATA[
<div class="document">
<p>Gosh, has it been three months since I posted last? House renos are coming along, but it only gets worse from here before it gets better. We'll be cooking on the patio soon enough.</p>
<p>Semi-random tech link of the day: FreeBSD <a class="reference external" href="http://miwi.bsdcrew.de/2009/06/python-262-now-default-on-freebsd-portstree/">ports now default to Python 2.6</a>. Yay. You could always force FreeBSD to use a specific Python version -- edit <tt class="docutils literal"><span class="pre">/etc/make.conf</span></tt> and add the line <tt class="docutils literal"><span class="pre">PYTHON_DEFAULT_VERSION=python2.6</span></tt> or whatever version you like.</p>
<p>I smell a skunk nearby. No, really, they like to walk down the sidewalk past my office window. Unpleasant, but not nearly as bad as having them spray the house. And this leads me to the skunk control tip of the day: do not try to dissuade two skunks from fighting at 2am in the morning below your kitchen window by throwing water at them.</p>
</div>

]]></description>
  <guid isPermaLink="false">tag:mikewatkins.ca,2007-10-10:journal:mw:entry:709</guid>
  <pubDate>Sun, 14 Jun 2009 09:32:24 GMT</pubDate>
  <category>freebsd</category>
  <category>python</category>
</item>
<item>
  <title>Tyrannical Databases</title>
  <link>http://mikewatkins.ca/2009/03/12/tyrannical-databases/</link>
  <description><![CDATA[
<div class="document">
<p>Inspired by a series of slides <a class="reference external" href="http://michael.susens-schurter.com/blog/2009/03/11/tokyo-cabinet-pytyrant-talk/">Michael Schurter published</a> on <em>Tokyo Cabinet</em> and <em>PyTyrant</em>, I thought I'd code up his examples using another database which can use a key-value approach, <a class="reference external" href="http://www.mems-exchange.org/software/durus/">Durus</a>.</p>
<p>Durus is a ZODB work-a-like which allows for easy persistence of <em>Python objects</em>, not just values. It's simple, fast, and useful.</p>
<p>Here's the baseline Tokyo Cabinet db example Michael published, using the pytc interface:</p>
<div class="highlight"><pre><span class="kn">import</span> <span class="nn">pytc</span>
<span class="n">db</span> <span class="o">=</span> <span class="n">pytc</span><span class="o">.</span><span class="n">HDB</span><span class="p">()</span>
<span class="n">db</span><span class="o">.</span><span class="n">open</span><span class="p">(</span><span class="s">&#39;test.tch&#39;</span><span class="p">,</span>  <span class="n">pytc</span><span class="o">.</span><span class="n">BDBOWRITER</span> <span class="o">|</span> <span class="n">pytc</span><span class="o">.</span><span class="n">BDBOREADER</span> <span class="o">|</span> <span class="n">pytc</span><span class="o">.</span><span class="n">BDBOCREAT</span><span class="p">)</span>
<span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mf">256</span><span class="p">):</span>
    <span class="n">v</span> <span class="o">=</span> <span class="nb">chr</span><span class="p">(</span><span class="n">i</span><span class="p">)</span>
    <span class="k">for</span> <span class="n">x</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mf">256</span><span class="p">):</span>
        <span class="n">db</span><span class="o">.</span><span class="n">put</span><span class="p">(</span><span class="nb">chr</span><span class="p">(</span><span class="n">x</span><span class="p">),</span> <span class="n">v</span><span class="p">)</span>
        <span class="n">db</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="nb">chr</span><span class="p">(</span><span class="n">x</span><span class="p">))</span>
</pre></div>
<p>Running it:</p>
<pre class="literal-block">
$ time python test.py
real    0m0.168s
user    0m0.157s
sys     0m0.010s
</pre>
<p>And here is a Durus example, accessing a local file-based storage:</p>
<div class="highlight"><pre><span class="c"># Durus example 1 - File-based persistent dictionary</span>
<span class="kn">from</span> <span class="nn">durus.file_storage</span> <span class="kn">import</span> <span class="n">FileStorage</span>
<span class="kn">from</span> <span class="nn">durus.connection</span> <span class="kn">import</span> <span class="n">Connection</span>

<span class="n">conn</span> <span class="o">=</span> <span class="n">Connection</span><span class="p">(</span><span class="n">FileStorage</span><span class="p">(</span><span class="s">&#39;test.durus&#39;</span><span class="p">))</span>
<span class="n">db</span> <span class="o">=</span> <span class="n">conn</span><span class="o">.</span><span class="n">get_root</span><span class="p">()</span>
<span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mf">256</span><span class="p">):</span>
    <span class="n">v</span> <span class="o">=</span> <span class="nb">chr</span><span class="p">(</span><span class="n">i</span><span class="p">)</span>
    <span class="k">for</span> <span class="n">x</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mf">256</span><span class="p">):</span>
        <span class="n">db</span><span class="p">[</span><span class="nb">chr</span><span class="p">(</span><span class="n">x</span><span class="p">)]</span> <span class="o">=</span> <span class="n">v</span>
        <span class="n">db</span><span class="p">[</span><span class="nb">chr</span><span class="p">(</span><span class="n">x</span><span class="p">)]</span>
<span class="n">conn</span><span class="o">.</span><span class="n">commit</span><span class="p">()</span>
</pre></div>
<p>Running it:</p>
<pre class="literal-block">
$ time python durus-test.py
real        0m0.197s
user        0m0.187s
sys         0m0.008s
</pre>
<p>Now lets change to client-server operation, delivering more or less the same abilities as PyTyrant/Tokyo cabinet. A minor change to <tt class="docutils literal"><span class="pre">durus-test.py</span></tt> gives us a client:</p>
<div class="highlight"><pre><span class="c"># Durus example 2 - Remote access to a File-based persistent dictionary</span>
<span class="kn">from</span> <span class="nn">durus.client_storage</span> <span class="kn">import</span> <span class="n">ClientStorage</span>
<span class="kn">from</span> <span class="nn">durus.connection</span> <span class="kn">import</span> <span class="n">Connection</span>

<span class="n">conn</span> <span class="o">=</span> <span class="n">Connection</span><span class="p">(</span><span class="n">ClientStorage</span><span class="p">())</span>
<span class="n">db</span> <span class="o">=</span> <span class="n">conn</span><span class="o">.</span><span class="n">get_root</span><span class="p">()</span>
<span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mf">256</span><span class="p">):</span>
    <span class="n">v</span> <span class="o">=</span> <span class="nb">chr</span><span class="p">(</span><span class="n">i</span><span class="p">)</span>
    <span class="k">for</span> <span class="n">x</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mf">256</span><span class="p">):</span>
        <span class="n">db</span><span class="p">[</span><span class="nb">chr</span><span class="p">(</span><span class="n">x</span><span class="p">)]</span> <span class="o">=</span> <span class="n">v</span>
        <span class="n">db</span><span class="p">[</span><span class="nb">chr</span><span class="p">(</span><span class="n">x</span><span class="p">)]</span>
<span class="n">conn</span><span class="o">.</span><span class="n">commit</span><span class="p">()</span>
</pre></div>
<p>In between each run we'll remove the database file. We'll need a server running, so in another terminal lets fire one up:</p>
<pre class="literal-block">
$ rm test.durus
$ durus -s --file test.durus
</pre>
<p>Run the second example:</p>
<pre class="literal-block">
$ time python durus-remote-test.py
real        0m0.204s
user        0m0.189s
sys         0m0.013s
</pre>
<p>Lets use a more advanced container than a persistent dictionary, a BTree. First Tokyo Cabinet/pytc:</p>
<div class="highlight"><pre><span class="kn">import</span> <span class="nn">pytc</span>
<span class="n">db</span> <span class="o">=</span> <span class="n">pytc</span><span class="o">.</span><span class="n">BDB</span><span class="p">()</span>
<span class="n">db</span><span class="o">.</span><span class="n">open</span><span class="p">(</span><span class="s">&#39;test.db&#39;</span><span class="p">,</span>  <span class="n">pytc</span><span class="o">.</span><span class="n">BDBOWRITER</span> <span class="o">|</span> <span class="n">pytc</span><span class="o">.</span><span class="n">BDBOREADER</span> <span class="o">|</span> <span class="n">pytc</span><span class="o">.</span><span class="n">BDBOCREAT</span><span class="p">)</span>
<span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mf">256</span><span class="p">):</span>
    <span class="n">v</span> <span class="o">=</span> <span class="nb">chr</span><span class="p">(</span><span class="n">i</span><span class="p">)</span>
    <span class="k">for</span> <span class="n">x</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mf">256</span><span class="p">):</span>
        <span class="n">db</span><span class="o">.</span><span class="n">put</span><span class="p">(</span><span class="nb">chr</span><span class="p">(</span><span class="n">x</span><span class="p">),</span> <span class="n">v</span><span class="p">)</span>
        <span class="n">db</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="nb">chr</span><span class="p">(</span><span class="n">x</span><span class="p">))</span>
</pre></div>
<p>Running pytc with the BTree:</p>
<pre class="literal-block">
$ time python test.py

real    0m0.169s
user    0m0.157s
sys     0m0.011s
</pre>
<p>Nice and fast - its all C-based.</p>
<p>Now the Durus BTree code:</p>
<div class="highlight"><pre><span class="c"># Durus example 3 - File-based persistent BTree</span>
<span class="kn">from</span> <span class="nn">durus.file_storage</span> <span class="kn">import</span> <span class="n">FileStorage</span>
<span class="kn">from</span> <span class="nn">durus.connection</span> <span class="kn">import</span> <span class="n">Connection</span>
<span class="kn">from</span> <span class="nn">durus.btree</span> <span class="kn">import</span> <span class="n">BTree</span>

<span class="n">conn</span> <span class="o">=</span> <span class="n">Connection</span><span class="p">(</span><span class="n">FileStorage</span><span class="p">(</span><span class="s">&#39;test.durus&#39;</span><span class="p">))</span>
<span class="n">root</span> <span class="o">=</span> <span class="n">conn</span><span class="o">.</span><span class="n">get_root</span><span class="p">()</span>
<span class="n">db</span> <span class="o">=</span> <span class="n">BTree</span><span class="p">()</span>
<span class="n">root</span><span class="p">[</span><span class="s">&#39;db&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="n">db</span>
<span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mf">256</span><span class="p">):</span>
    <span class="n">v</span> <span class="o">=</span> <span class="nb">chr</span><span class="p">(</span><span class="n">i</span><span class="p">)</span>
    <span class="k">for</span> <span class="n">x</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mf">256</span><span class="p">):</span>
        <span class="n">db</span><span class="p">[</span><span class="nb">chr</span><span class="p">(</span><span class="n">x</span><span class="p">)]</span> <span class="o">=</span> <span class="n">v</span>
        <span class="n">db</span><span class="p">[</span><span class="nb">chr</span><span class="p">(</span><span class="n">x</span><span class="p">)]</span>
<span class="n">conn</span><span class="o">.</span><span class="n">commit</span><span class="p">()</span>
</pre></div>
<p>Running this we see a significant performance delta compared to the C-based pytc/Tokyo Cabinet:</p>
<pre class="literal-block">
$ time python durus-btree.py
real        0m1.319s
user        0m1.308s
sys         0m0.011s
</pre>
<p>The delta will tip back into Durus's favour in the next two examples.</p>
<div class="highlight"><pre><span class="c"># Durus example 4 - client-server access to a persistent BTree</span>
<span class="kn">from</span> <span class="nn">durus.client_storage</span> <span class="kn">import</span> <span class="n">ClientStorage</span>
<span class="kn">from</span> <span class="nn">durus.connection</span> <span class="kn">import</span> <span class="n">Connection</span>
<span class="kn">from</span> <span class="nn">durus.btree</span> <span class="kn">import</span> <span class="n">BTree</span>

<span class="n">conn</span> <span class="o">=</span> <span class="n">Connection</span><span class="p">(</span><span class="n">ClientStorage</span><span class="p">())</span>
<span class="n">root</span> <span class="o">=</span> <span class="n">conn</span><span class="o">.</span><span class="n">get_root</span><span class="p">()</span>
<span class="n">db</span> <span class="o">=</span> <span class="n">BTree</span><span class="p">()</span>
<span class="n">root</span><span class="p">[</span><span class="s">&#39;db&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="n">db</span>
<span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mf">256</span><span class="p">):</span>
    <span class="n">v</span> <span class="o">=</span> <span class="nb">chr</span><span class="p">(</span><span class="n">i</span><span class="p">)</span>
    <span class="k">for</span> <span class="n">x</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mf">256</span><span class="p">):</span>
        <span class="n">db</span><span class="p">[</span><span class="nb">chr</span><span class="p">(</span><span class="n">x</span><span class="p">)]</span> <span class="o">=</span> <span class="n">v</span>
        <span class="n">db</span><span class="p">[</span><span class="nb">chr</span><span class="p">(</span><span class="n">x</span><span class="p">)]</span>
<span class="n">conn</span><span class="o">.</span><span class="n">commit</span><span class="p">()</span>
</pre></div>
<p>First, the access the BTree-based &quot;db&quot; via client-server:</p>
<pre class="literal-block">
$ time python durus-remote-btree-adding.py
real        0m1.691s
user        0m1.681s
sys         0m0.010s
</pre>
<p>Next we see that read only access, remote or local, remains fast, even with the BTree structure:</p>
<pre class="literal-block">
$ time python durus-remote-btree-ro.py
real        0m0.054s
user        0m0.040s
sys         0m0.012s
</pre>
<p>PyTyrant / TokyoCabinet has a nice simple API to accessing the remote server:</p>
<div class="highlight"><pre><span class="kn">import</span> <span class="nn">pytyrant</span>

<span class="n">t</span> <span class="o">=</span> <span class="n">pytyrant</span><span class="o">.</span><span class="n">PyTyrant</span><span class="o">.</span><span class="n">open</span><span class="p">(</span><span class="s">&#39;127.0.0.1&#39;</span><span class="p">,</span> <span class="mf">1978</span><span class="p">)</span>
<span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mf">256</span><span class="p">):</span>
    <span class="n">v</span> <span class="o">=</span> <span class="nb">chr</span><span class="p">(</span><span class="n">i</span><span class="p">)</span>
    <span class="k">for</span> <span class="n">x</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mf">256</span><span class="p">):</span>
        <span class="n">t</span><span class="p">[</span><span class="nb">chr</span><span class="p">(</span><span class="n">x</span><span class="p">)]</span> <span class="o">=</span> <span class="n">v</span>
        <span class="n">t</span><span class="p">[</span><span class="nb">chr</span><span class="p">(</span><span class="n">x</span><span class="p">)]</span>
</pre></div>
<p>PyTyrant client-server access to a BTree structure suggests future room for improvement:</p>
<pre class="literal-block">
$ time python pyt-test.py

real    0m11.151s
user    0m1.317s
sys     0m1.653s
</pre>
<p>Of course raw throughput isn't everything. Durus has persistent container types including Dictionary,
BTree, Set and Lists. Keys in mappings can be any hashable object; values can
be any pickleable object. Durus objects are Python objects, not merely strings or values.</p>
<p>Consider the following:</p>
<div class="highlight"><pre><span class="err">$</span> <span class="n">durus</span> <span class="o">-</span><span class="n">c</span>
<span class="n">Durus</span> <span class="mf">127.0</span><span class="o">.</span><span class="mf">0.1</span><span class="p">:</span><span class="mf">2972</span>
    <span class="n">connection</span> <span class="o">-&gt;</span> <span class="n">the</span> <span class="n">Connection</span>
    <span class="n">root</span>       <span class="o">-&gt;</span> <span class="n">the</span> <span class="n">root</span> <span class="n">instance</span>
<span class="o">&gt;&gt;&gt;</span> <span class="kn">from</span> <span class="nn">durus.persistent_dict</span> <span class="kn">import</span> <span class="n">PersistentDict</span>
<span class="o">&gt;&gt;&gt;</span> <span class="n">names</span> <span class="o">=</span> <span class="n">PersistentDict</span><span class="p">()</span>
<span class="o">&gt;&gt;&gt;</span> <span class="n">root</span><span class="p">[</span><span class="s">&#39;names&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="n">names</span>
<span class="o">&gt;&gt;&gt;</span> <span class="n">connection</span><span class="o">.</span><span class="n">commit</span><span class="p">()</span>
<span class="o">&gt;&gt;&gt;</span> <span class="n">mike</span> <span class="o">=</span> <span class="s">&#39;Mike Watkins&#39;</span>
<span class="o">&gt;&gt;&gt;</span> <span class="n">fred</span> <span class="o">=</span> <span class="s">&#39;Fred Astaire&#39;</span>
<span class="o">&gt;&gt;&gt;</span> <span class="n">ringo</span> <span class="o">=</span> <span class="s">&#39;Ringo Starr&#39;</span>
<span class="o">&gt;&gt;&gt;</span> <span class="n">names</span><span class="p">[</span><span class="mf">1</span><span class="p">]</span> <span class="o">=</span> <span class="n">mike</span>
<span class="o">&gt;&gt;&gt;</span> <span class="n">names</span><span class="p">[</span><span class="mf">2</span><span class="p">]</span> <span class="o">=</span> <span class="n">fred</span>
<span class="o">&gt;&gt;&gt;</span> <span class="n">names</span><span class="p">[</span><span class="mf">3</span><span class="p">]</span> <span class="o">=</span> <span class="n">ringo</span>
<span class="o">&gt;&gt;&gt;</span> <span class="n">names</span><span class="p">[</span><span class="mf">22</span><span class="p">]</span> <span class="o">=</span> <span class="n">fred</span>
<span class="o">&gt;&gt;&gt;</span> <span class="nb">id</span><span class="p">(</span><span class="n">names</span><span class="p">[</span><span class="mf">2</span><span class="p">])</span>
<span class="mf">3082202976</span>
<span class="o">&gt;&gt;&gt;</span> <span class="nb">id</span><span class="p">(</span><span class="n">names</span><span class="p">[</span><span class="mf">22</span><span class="p">])</span>
<span class="mf">3082202976</span>
<span class="o">&gt;&gt;&gt;</span> <span class="n">connection</span><span class="o">.</span><span class="n">commit</span><span class="p">()</span>
</pre></div>
<p>When we reconnect, we should expect the values within the mapping at keys 2 and 22 to be the same <em>object</em>:</p>
<div class="highlight"><pre><span class="err">$</span> <span class="n">durus</span> <span class="o">-</span><span class="n">c</span>
<span class="n">Durus</span> <span class="mf">127.0</span><span class="o">.</span><span class="mf">0.1</span><span class="p">:</span><span class="mf">2972</span>
    <span class="n">connection</span> <span class="o">-&gt;</span> <span class="n">the</span> <span class="n">Connection</span>
    <span class="n">root</span>       <span class="o">-&gt;</span> <span class="n">the</span> <span class="n">root</span> <span class="n">instance</span>
<span class="o">&gt;&gt;&gt;</span> <span class="n">names</span> <span class="o">=</span> <span class="n">root</span><span class="p">[</span><span class="s">&#39;names&#39;</span><span class="p">]</span>
<span class="o">&gt;&gt;&gt;</span> <span class="nb">id</span><span class="p">(</span><span class="n">names</span><span class="p">[</span><span class="mf">2</span><span class="p">])</span>
<span class="mf">3081790720</span>
<span class="o">&gt;&gt;&gt;</span> <span class="nb">id</span><span class="p">(</span><span class="n">names</span><span class="p">[</span><span class="mf">22</span><span class="p">])</span>
<span class="mf">3081790720</span>
<span class="o">&gt;&gt;&gt;</span> <span class="nb">id</span><span class="p">(</span><span class="n">names</span><span class="p">[</span><span class="mf">2</span><span class="p">])</span> <span class="o">==</span> <span class="nb">id</span><span class="p">(</span><span class="n">names</span><span class="p">[</span><span class="mf">22</span><span class="p">])</span>
<span class="bp">True</span>
</pre></div>
<p>Of late there seems to be plenty of interest in non-SQL database architectures -- CouchDB, Tokyo Cabinet among others getting attention, in part because they offer a language agnostic solution.</p>
<p>For those many other times when a project will benefit from a persistence layer tightly coupled with the language, object databases like Durus or ZODB are worthy of consideration.</p>
</div>

]]></description>
  <guid isPermaLink="false">tag:mikewatkins.ca,2007-10-10:journal:mw:entry:701</guid>
  <pubDate>Thu, 12 Mar 2009 04:54:48 GMT</pubDate>
  <category>durus</category>
  <category>python</category>
</item>
<item>
  <title>Reducing RAM resource usage on a VPS</title>
  <link>http://mikewatkins.ca/2009/03/10/reducing-ram-resource-usage-on-a-vps/</link>
  <description><![CDATA[
<div class="document">
<p>Here are some miscellaneous notes as I tweak a new virtual private server (VPS). It's a time of fear and wonder as I'm leaving FreeBSD's ample and soft bosom for the as yet unknown pleasures to be found in the arms of my new Debian lover.</p>
<dl class="docutils">
<dt>HTTP Daemon:</dt>
<dd><p class="first">Problem? I think it's self evident.  Yes, I know you can tune Apache and yes, I've been down that road before myself, but nothing I've done to tune Apache beats a simple <tt class="docutils literal"><span class="pre">lighttpd</span></tt> implementation, at least not with my application stack.</p>
<p>Solution: Uninstall Apache. Install <tt class="docutils literal"><span class="pre">lighttpd</span></tt>.</p>
<p>As a bonus, <a class="reference external" href="http://www.lighttpd.net/">lighttpd</a> supports SCGI (and FCGI) natively (to my knowledge, another popular lightweight httpd - <a class="reference external" href="http://nginx.net/">nginx</a> - does not support SCGI natively although contribs are available) which gives you deployment options for a variety of <a class="reference external" href="http://www.djangoproject.com/">popular</a> and <a class="reference external" href="http://www.mems-exchange.org/software/qp/">not so popular</a> Python web application frameworks.</p>
<p>Incidentally, QP deployed with SCGI (whether via <tt class="docutils literal"><span class="pre">lighttpd</span></tt> or Apache <tt class="docutils literal"><span class="pre">httpd</span></tt>) provides a nice combo that would be compatible with a multi-user shared hosting environment.</p>
<p class="last">One of these days I'll get off my but and migrate my weblog over, and enable comments here in doing so, in order that I can satisfy a selfish desire to ask the <em>lazy web</em> if anyone has worked with a reasonable webmail application developed in Python. I'd really like to avoid supporting PHP in the future and at this point I only support PHP for a webmail application.</p>
</dd>
</dl>
<dl class="docutils">
<dt>rsyslogd</dt>
<dd><p class="first">This daemon appears to be the default system logging daemon on Debian; for some reason it uses many times more RAM than the default FreeBSD syslogd, even when it isn't actually doing any remote logging.</p>
<p class="last">Solution: Add a call to <tt class="docutils literal"><span class="pre">ulimit</span> <span class="pre">-s</span> <span class="pre">128</span></tt> in <tt class="docutils literal"><span class="pre">do_start()</span></tt> in <tt class="docutils literal"><span class="pre">/etc/init.d/rsyslog</span></tt> before the daemon is started to reduce the stack size.</p>
</dd>
<dt>DNS</dt>
<dd><p class="first"><tt class="docutils literal"><span class="pre">bind9</span></tt> is a huge monster, something not often needed for a VPS or dedicated server that might need to also be an authoritative name server for a few domains. I'm sure there is some tweaking that can be done to reduce its footprint (no threads?) but for a clean break lets try another.</p>
<p class="last">Solution: <a class="reference external" href="http://www.maradns.org/">MaraDNS</a>. Simple to configure (not that <tt class="docutils literal"><span class="pre">bind</span></tt> is all that hard, but some complain just the same), fast, and small. Config file uses Python syntax (n.b. use &quot;somevalue&quot; rather than single quotes 'some value').</p>
</dd>
</dl>
<p><strong>Total savings so far</strong>: 80 - 120MB (more if one factors in Apache), which is pretty substantial given many low end VPS accounts start at 64 - 128MB of RAM allocation.</p>
</div>

]]></description>
  <guid isPermaLink="false">tag:mikewatkins.ca,2007-10-10:journal:mw:entry:700</guid>
  <pubDate>Wed, 11 Mar 2009 03:03:38 GMT</pubDate>
  <category>debian</category>
  <category>python</category>
  <category>technical</category>
  <category>vps</category>
</item>
</channel></rss>
