<?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>schmichael&#039;s blog &#187; Python</title>
	<atom:link href="http://blog.schmichael.com/tag/python/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.schmichael.com</link>
	<description>good good study, day day up</description>
	<lastBuildDate>Sat, 05 Nov 2011 23:13:47 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.2.1</generator>
		<item>
		<title>Sharing Python data between processes using mmap</title>
		<link>http://blog.schmichael.com/2011/05/15/sharing-python-data-between-processes-using-mmap/</link>
		<comments>http://blog.schmichael.com/2011/05/15/sharing-python-data-between-processes-using-mmap/#comments</comments>
		<pubDate>Mon, 16 May 2011 04:28:29 +0000</pubDate>
		<dc:creator>Michael Schurter</dc:creator>
				<category><![CDATA[GNU/Linux]]></category>
		<category><![CDATA[Open Source]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[Technology]]></category>
		<category><![CDATA[ctypes]]></category>
		<category><![CDATA[mmap]]></category>
		<category><![CDATA[struct]]></category>

		<guid isPermaLink="false">http://blog.schmichael.com/?p=947</guid>
		<description><![CDATA[I&#8217;ve been toying with an idea of exposing statistics for a Python application via shared memory to keep the performance impact on the application as low as possible. The goal being an application could passively expose a number of metrics &#8230; <a href="http://blog.schmichael.com/2011/05/15/sharing-python-data-between-processes-using-mmap/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve been toying with an idea of exposing statistics for a Python application via shared memory to keep the performance impact on the application as low as possible. The goal being an application could passively expose a number of metrics that could either be periodically polled via <a href="http://munin-monitoring.org/">munin</a>/<a href="http://www.icinga.org/">Icinga</a>/etc plugins or interactive tools when diagnosing issues on a system.</p>
<p>But first things first: I need to put data into <a href="http://en.wikipedia.org/wiki/Shared_memory">shared memory</a> from Python. <a href="http://en.wikipedia.org/wiki/Mmap">mmap</a> is an excellent widely-implemented POSIX system call for creating a shared memory space backed by an on-disk file.</p>
<p>Usually in the UNIX world you have 2 ways of accessing/manipulating data: memory addresses or streams (files). Manipulating data via memory addresses means <a href="http://en.wikipedia.org/wiki/Pointer_%28computing%29">pointers</a>, offsets, <a href="http://en.wikipedia.org/wiki/Malloc">malloc/free</a>, etc. Stream interfaces manipulate data via <a href="http://en.wikipedia.org/wiki/System_call">read/write/seek system calls</a> for files and <a href="http://en.wikipedia.org/wiki/Berkeley_sockets">send/recv/etc for sockets</a>.</p>
<p>mmap gives you both interfaces. A memory mapped file can be manipulated via read/write/seek or by directly accessing its mapped memory region. The advantage of the latter is that this memory region is in userspace &#8212; meaning you can manipulate a file without incurring the overhead of write system calls for every manipulation.</p>
<p>Anyway, enough exposition, let&#8217;s see some code. <small>(Despite mmap&#8217;s nice featureset, I&#8217;m only using it as a simple memory sharing mechanism anyway.)</small> The following code shares a tiny bit of data between 2 Python processes using the excellent <a href="http://docs.python.org/library/mmap">mmap module in the stdlib</a>. <code>a.py</code> writes to the memory mapped region, and <code>b.py</code> reads the data out. <a href="http://docs.python.org/library/ctypes">ctypes</a> allows for an easy way to create values in a memory mapped region and manipulate them like &#8220;normal&#8221; Python objects.</p>
<p><em>These code samples were written using Python 2.7 on Linux. They should work fine on any POSIX system, but Windows users will have to change the mmap calls to match the Windows API.</em></p>
<p><strong>a.py</strong></p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #808080; font-style: italic;">#!/usr/bin/env python</span>
<span style="color: #ff7700;font-weight:bold;">import</span> ctypes
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">mmap</span>
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">os</span>
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">struct</span>
&nbsp;
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> main<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
    <span style="color: #808080; font-style: italic;"># Create new empty file to back memory map on disk</span>
    fd = <span style="color: #dc143c;">os</span>.<span style="color: #008000;">open</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'/tmp/mmaptest'</span>, <span style="color: #dc143c;">os</span>.<span style="color: black;">O_CREAT</span> | <span style="color: #dc143c;">os</span>.<span style="color: black;">O_TRUNC</span> | <span style="color: #dc143c;">os</span>.<span style="color: black;">O_RDWR</span><span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #808080; font-style: italic;"># Zero out the file to insure it's the right size</span>
    <span style="color: #ff7700;font-weight:bold;">assert</span> <span style="color: #dc143c;">os</span>.<span style="color: black;">write</span><span style="color: black;">&#40;</span>fd, <span style="color: #483d8b;">'<span style="color: #000099; font-weight: bold;">\x</span>00'</span> <span style="color: #66cc66;">*</span> <span style="color: #dc143c;">mmap</span>.<span style="color: black;">PAGESIZE</span><span style="color: black;">&#41;</span> == <span style="color: #dc143c;">mmap</span>.<span style="color: black;">PAGESIZE</span>
&nbsp;
    <span style="color: #808080; font-style: italic;"># Create the mmap instace with the following params:</span>
    <span style="color: #808080; font-style: italic;"># fd: File descriptor which backs the mapping or -1 for anonymous mapping</span>
    <span style="color: #808080; font-style: italic;"># length: Must in multiples of PAGESIZE (usually 4 KB)</span>
    <span style="color: #808080; font-style: italic;"># flags: MAP_SHARED means other processes can share this mmap</span>
    <span style="color: #808080; font-style: italic;"># prot: PROT_WRITE means this process can write to this mmap</span>
    buf = <span style="color: #dc143c;">mmap</span>.<span style="color: #dc143c;">mmap</span><span style="color: black;">&#40;</span>fd, <span style="color: #dc143c;">mmap</span>.<span style="color: black;">PAGESIZE</span>, <span style="color: #dc143c;">mmap</span>.<span style="color: black;">MAP_SHARED</span>, <span style="color: #dc143c;">mmap</span>.<span style="color: black;">PROT_WRITE</span><span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #808080; font-style: italic;"># Now create an int in the memory mapping</span>
    i = ctypes.<span style="color: black;">c_int</span>.<span style="color: black;">from_buffer</span><span style="color: black;">&#40;</span>buf<span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #808080; font-style: italic;"># Set a value</span>
    i.<span style="color: black;">value</span> = <span style="color: #ff4500;">10</span>
&nbsp;
    <span style="color: #808080; font-style: italic;"># And manipulate it for kicks</span>
    i.<span style="color: black;">value</span> += <span style="color: #ff4500;">1</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">assert</span> i.<span style="color: black;">value</span> == <span style="color: #ff4500;">11</span>
&nbsp;
    <span style="color: #808080; font-style: italic;"># Before we create a new value, we need to find the offset of the next free</span>
    <span style="color: #808080; font-style: italic;"># memory address within the mmap</span>
    offset = <span style="color: #dc143c;">struct</span>.<span style="color: black;">calcsize</span><span style="color: black;">&#40;</span>i._type_<span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #808080; font-style: italic;"># The offset should be uninitialized ('\x00')</span>
    <span style="color: #ff7700;font-weight:bold;">assert</span> buf<span style="color: black;">&#91;</span>offset<span style="color: black;">&#93;</span> == <span style="color: #483d8b;">'<span style="color: #000099; font-weight: bold;">\x</span>00'</span>
&nbsp;
    <span style="color: #808080; font-style: italic;"># Now ceate a string containing 'foo' by first creating a c_char array</span>
    s_type = ctypes.<span style="color: black;">c_char</span> <span style="color: #66cc66;">*</span> <span style="color: #008000;">len</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'foo'</span><span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #808080; font-style: italic;"># Now create the ctypes instance</span>
    s = s_type.<span style="color: black;">from_buffer</span><span style="color: black;">&#40;</span>buf, offset<span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #808080; font-style: italic;"># And finally set it</span>
    s.<span style="color: black;">raw</span> = <span style="color: #483d8b;">'foo'</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">'First 10 bytes of memory mapping: %r'</span> <span style="color: #66cc66;">%</span> buf<span style="color: black;">&#91;</span>:<span style="color: #ff4500;">10</span><span style="color: black;">&#93;</span>
    <span style="color: #008000;">raw_input</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'Now run b.py and press ENTER'</span><span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">print</span>
    <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">'Changing i'</span>
    i.<span style="color: black;">value</span> <span style="color: #66cc66;">*</span>= i.<span style="color: black;">value</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">'Changing s'</span>
    s.<span style="color: black;">raw</span> = <span style="color: #483d8b;">'bar'</span>
&nbsp;
    new_i = <span style="color: #008000;">raw_input</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'Enter a new value for i: '</span><span style="color: black;">&#41;</span>
    i.<span style="color: black;">value</span> = <span style="color: #008000;">int</span><span style="color: black;">&#40;</span>new_i<span style="color: black;">&#41;</span>
&nbsp;
&nbsp;
<span style="color: #ff7700;font-weight:bold;">if</span> __name__ == <span style="color: #483d8b;">'__main__'</span>:
    main<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span></pre></div></div>

<p><strong>b.py</strong></p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">mmap</span>
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">os</span>
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">struct</span>
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">time</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> main<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
    <span style="color: #808080; font-style: italic;"># Open the file for reading</span>
    fd = <span style="color: #dc143c;">os</span>.<span style="color: #008000;">open</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'/tmp/mmaptest'</span>, <span style="color: #dc143c;">os</span>.<span style="color: black;">O_RDONLY</span><span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #808080; font-style: italic;"># Memory map the file</span>
    buf = <span style="color: #dc143c;">mmap</span>.<span style="color: #dc143c;">mmap</span><span style="color: black;">&#40;</span>fd, <span style="color: #dc143c;">mmap</span>.<span style="color: black;">PAGESIZE</span>, <span style="color: #dc143c;">mmap</span>.<span style="color: black;">MAP_SHARED</span>, <span style="color: #dc143c;">mmap</span>.<span style="color: black;">PROT_READ</span><span style="color: black;">&#41;</span>
&nbsp;
    i = <span style="color: #008000;">None</span>
    s = <span style="color: #008000;">None</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">while</span> <span style="color: #ff4500;">1</span>:
        new_i, = <span style="color: #dc143c;">struct</span>.<span style="color: black;">unpack</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'i'</span>, buf<span style="color: black;">&#91;</span>:<span style="color: #ff4500;">4</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span>
        new_s, = <span style="color: #dc143c;">struct</span>.<span style="color: black;">unpack</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'3s'</span>, buf<span style="color: black;">&#91;</span><span style="color: #ff4500;">4</span>:<span style="color: #ff4500;">7</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span>
&nbsp;
        <span style="color: #ff7700;font-weight:bold;">if</span> i <span style="color: #66cc66;">!</span>= new_i <span style="color: #ff7700;font-weight:bold;">or</span> s <span style="color: #66cc66;">!</span>= new_s:
            <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">'i: %s =&gt; %d'</span> <span style="color: #66cc66;">%</span> <span style="color: black;">&#40;</span>i, new_i<span style="color: black;">&#41;</span>
            <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">'s: %s =&gt; %s'</span> <span style="color: #66cc66;">%</span> <span style="color: black;">&#40;</span>s, new_s<span style="color: black;">&#41;</span>
            <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">'Press Ctrl-C to exit'</span>
            i = new_i
            s = new_s
&nbsp;
        <span style="color: #dc143c;">time</span>.<span style="color: black;">sleep</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">1</span><span style="color: black;">&#41;</span>
&nbsp;
&nbsp;
<span style="color: #ff7700;font-weight:bold;">if</span> __name__ == <span style="color: #483d8b;">'__main__'</span>:
    main<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span></pre></div></div>

<p><small>(Note that I cruelly don&#8217;t clean up /tmp/mmaptest after the scripts finished. Consider it a 4KB tax for anyone who runs arbitrary code they found on the Internet without reading it first.)</small></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.schmichael.com/2011/05/15/sharing-python-data-between-processes-using-mmap/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Switched tc-rest to webob</title>
		<link>http://blog.schmichael.com/2009/08/10/switched-tc-est-to-webob/</link>
		<comments>http://blog.schmichael.com/2009/08/10/switched-tc-est-to-webob/#comments</comments>
		<pubDate>Tue, 11 Aug 2009 06:12:56 +0000</pubDate>
		<dc:creator>Michael Schurter</dc:creator>
				<category><![CDATA[Open Source]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[Technology]]></category>
		<category><![CDATA[bitbucket]]></category>
		<category><![CDATA[fapws3]]></category>
		<category><![CDATA[tc-rest]]></category>
		<category><![CDATA[tokyo cabinet]]></category>

		<guid isPermaLink="false">http://michael.susens-schurter.com/blog/?p=704</guid>
		<description><![CDATA[Small update on my toy tc-rest project: I switched to using WebOb for creating HTTP Request and Response objects. Cleaned up the code a bit, but a real dispatcher is what&#8217;s needed to really remove the cruft. I&#8217;m anxious to &#8230; <a href="http://blog.schmichael.com/2009/08/10/switched-tc-est-to-webob/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Small update on my toy tc-rest project: I switched to using <a href="http://pythonpaste.org/webob/">WebOb</a> for creating HTTP Request and Response objects.  Cleaned up the code a bit, but a real dispatcher is what&#8217;s needed to really remove the cruft.</p>
<p>I&#8217;m anxious to extend the API and add features, but I have no clue when I&#8217;ll have time to touch it again.  In the mean time I&#8217;ve <a href="http://bitbucket.org/schmichael/tc-rest/overview/">pushed tc-rest to bitbucket.org if you want to take a look</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.schmichael.com/2009/08/10/switched-tc-est-to-webob/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>TokyoCabinet + fapws3 = tc-rest</title>
		<link>http://blog.schmichael.com/2009/08/08/tokyocabinet-fapws3-tc-rest/</link>
		<comments>http://blog.schmichael.com/2009/08/08/tokyocabinet-fapws3-tc-rest/#comments</comments>
		<pubDate>Sun, 09 Aug 2009 05:53:12 +0000</pubDate>
		<dc:creator>Michael Schurter</dc:creator>
				<category><![CDATA[Open Source]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[Technology]]></category>
		<category><![CDATA[fapws3]]></category>
		<category><![CDATA[tc-rest]]></category>
		<category><![CDATA[tokyo cabinet]]></category>

		<guid isPermaLink="false">http://michael.susens-schurter.com/blog/?p=695</guid>
		<description><![CDATA[Have you ever wondered how hard it would be to tack a RESTful HTTP interface on top of a fast key/value database like TokyoCabinet? Probably not, but I did: tc-rest.tar.gz Components: TokyoCabinet &#8211; my favorite persistent key/value database pytc &#8211; &#8230; <a href="http://blog.schmichael.com/2009/08/08/tokyocabinet-fapws3-tc-rest/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Have you ever wondered how hard it would be to tack a RESTful HTTP interface on top of a fast key/value database like TokyoCabinet?</p>
<p>Probably not, but I did: <a href="http://blog.schmichael.com/files/tc-rest.tar.gz">tc-rest.tar.gz</a></p>
<p>Components:</p>
<ul>
<li><a href="http://tokyocabinet.sourceforge.net/">TokyoCabinet</a> &#8211; my favorite persistent key/value database</li>
<li><a href="http://pypi.python.org/pypi/pytc/">pytc</a> &#8211; a wonderful Python wrapper for TC</li>
<li><a href="http://github.com/william-os4y/fapws3/tree/master">fapws3</a> &#8211; a fast libev based HTTP/<a href="http://www.python.org/dev/peps/pep-0333/">WSGI</a> server</li>
<li><a href="http://code.google.com/p/simplejson/">simpleson</a> &#8211; (or Python >= 2.6) for encapsulating HTTP responses</li>
<li><a href="http://www.aminus.net/wiki/Okapi">okapi</a> &#8211; a fantastic little static HTML page for testing HTTP APIs</li>
</ul>
<p>Getting TokyoCabinet+pytc to work inside a <a href="http://pypi.python.org/pypi/virtualenv/">virtualenv</a> was a bit tricky, so check out my <code>run.sh</code> script if you&#8217;re having trouble getting it to start.</p>
<p>Once you get it started, load okapi in your browser:</p>
<p><a href="http://localhost:8080/static/okapi.html">http://localhost:8080/static/okapi.html</a></p>
<p>And then create a database by doing a POST like:</p>
<p><code>http://localhost:8080/foo/</code></p>
<p>And finally store/get keys and values using GET and POST requests like:</p>
<p><code>http://localhost:8080/foo/bar/</code><br />
<code>http://localhost:8080/foo/baz/</code></p>
<p>Doing a GET request to a database URL lists keys.</p>
<p>At any rate, I had big dreams for building a system where you would store JSON, specify indexes on certain keys, and the server would maintain those indexes for you by creating ad hoc TokyoCabinet databases.</p>
<p>Instead I ended up wasting most of my time learning how to write a low-level WSGI app.  I should have just used CherryPy or Django from the beginning, but I had never written a pure WSGI app before.  It was a good lesson even if it meant not getting some of my features implemented.</p>
<p>I&#8217;ll probably keep playing with this idea, but the next version will probably be based on some existing framework.  Parsing <code>environ['PATH_INFO']</code> and running <code>start_response(...)</code> manually gets old fast.</p>
<p>fapws3 is pretty neat, but had lots of annoying rough edges.  I had to manually create a <code>README</code> file because its setup.py expects one to exist.  Then I had to manually allow DELETE HTTP methods in fapws/base.py, otherwise it would return an HTML error message for me!  That was a bit shocking since I was working under the assumption fapws3 is just a low-level HTTP/WSGI server.</p>
<p><strong>Update</strong></p>
<ol>
<li><a href="http://michael.susens-schurter.com/blog/2009/03/11/tokyo-cabinet-pytyrant-talk/">If you&#8217;re new to TokyoCabinet, I posted my presentation on it that I did at Portland Python meetup</a>.</li>
<li>Someone want to benchmark this for me?  Might be interesting since its made with the fastest libs available in Python for their respective tasks.  I&#8217;m just feeling lazy at this point.  <img src='http://blog.schmichael.com/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> </li>
</ol>
]]></content:encoded>
			<wfw:commentRss>http://blog.schmichael.com/2009/08/08/tokyocabinet-fapws3-tc-rest/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Tokyo {Cabinet, [Py]Tyrant} Talk</title>
		<link>http://blog.schmichael.com/2009/03/11/tokyo-cabinet-pytyrant-talk/</link>
		<comments>http://blog.schmichael.com/2009/03/11/tokyo-cabinet-pytyrant-talk/#comments</comments>
		<pubDate>Wed, 11 Mar 2009 16:38:09 +0000</pubDate>
		<dc:creator>Michael Schurter</dc:creator>
				<category><![CDATA[Open Source]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[Technology]]></category>
		<category><![CDATA[pdxpython]]></category>
		<category><![CDATA[presentation]]></category>
		<category><![CDATA[pytyrant]]></category>
		<category><![CDATA[tokyo cabinet]]></category>
		<category><![CDATA[tokyo tyrant]]></category>

		<guid isPermaLink="false">http://michael.susens-schurter.com/blog/?p=578</guid>
		<description><![CDATA[I did an introductory talk on Tokyo Cabinet, Tokyo Tyrant, pytc, and PyTyrant at the Portland Python User Group meeting last night. It was definitely just an introductory talk, so if you&#8217;re already familiar with these projects it probably won&#8217;t &#8230; <a href="http://blog.schmichael.com/2009/03/11/tokyo-cabinet-pytyrant-talk/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>I did an introductory talk on <a href="http://tokyocabinet.sourceforge.net/index.html">Tokyo Cabinet</a>, <a href="http://tokyocabinet.sourceforge.net/tyrantdoc/">Tokyo Tyrant</a>, <a href="http://pypi.python.org/pypi/pytc/">pytc</a>, and <a href="http://code.google.com/p/pytyrant/">PyTyrant</a> at the <a href="http://www.pdxpython.org">Portland Python User Group</a> meeting last night.</p>
<p>It was definitely just an introductory talk, so if you&#8217;re already familiar with these projects it probably won&#8217;t be very interesting.</p>
<ul>
<li><a href="http://blog.schmichael.com/tokyotalk/">Slides (html)</a></li>
<li><a href="http://blog.schmichael.com/tokyotalk/tokyotalk.html">Single page (HTML version)</a></li>
<li><a href="http://blog.schmichael.com/tokyotalk/tokyotalk.pdf">Single page (PDF version)</a></li>
<li><a href="http://blog.schmichael.com/tokyotalk/tokyotalk.txt">reStructuredText (rst)  source</a></li>
</ul>
<p><strong>Errata:</strong> My slides state PyTyrant 1.1.11 doesn&#8217;t work with Tokyo Tyrant 1.1.17 &#8212; this is <em>wrong.</em>  I don&#8217;t know what I was doing yesterday, but today all my tests <em>work on Tokyo Tyrant 1.1.17</em>.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.schmichael.com/2009/03/11/tokyo-cabinet-pytyrant-talk/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>(Yet Another) Deploying Django with CherryPy Script</title>
		<link>http://blog.schmichael.com/2009/02/18/deploying-django-with-cherrypy/</link>
		<comments>http://blog.schmichael.com/2009/02/18/deploying-django-with-cherrypy/#comments</comments>
		<pubDate>Wed, 18 Feb 2009 23:36:06 +0000</pubDate>
		<dc:creator>Michael Schurter</dc:creator>
				<category><![CDATA[GNU/Linux]]></category>
		<category><![CDATA[Open Source]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[Technology]]></category>
		<category><![CDATA[cherrypy]]></category>
		<category><![CDATA[django]]></category>

		<guid isPermaLink="false">http://michael.susens-schurter.com/blog/?p=529</guid>
		<description><![CDATA[Recently I deployed a Django project on an OSX server. I foolishly thought this would be as easy as on Linux until I ran into the mess that is x86_64 Apache + mod_wsgi* + Django + psycopg2 + i386 PostgreSQL. &#8230; <a href="http://blog.schmichael.com/2009/02/18/deploying-django-with-cherrypy/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Recently I deployed a <a href="http://www.djangoproject.com/">Django</a> project on an OSX server.  I foolishly thought this would be as easy as on Linux until I ran into the mess that is <em>x86_64</em> Apache + <a href="http://www.modwsgi.org/">mod_wsgi</a>* + Django + psycopg2 + <em>i386</em> PostgreSQL.  After wasting far too much time googling and recompiling various bits trying to get everything happy, I followed <a href="http://www.eflorenzano.com/blog/post/hosting-django-site-pure-python/">Eric Florenzano&#8217;s post</a> on deploying Django using <a href="http://www.cherrypy.org/">CherryPy</a>&#8216;s** <a href="http://www.cherrypy.org/wiki/CherryPyDownload#StandaloneWSGIserver">wsgiserver</a>.</p>
<p>Here&#8217;s my lightly modified version of Eric&#8217;s script:</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">import</span> wsgiserver
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">sys</span>
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">os</span>
<span style="color: #ff7700;font-weight:bold;">import</span> django.<span style="color: black;">core</span>.<span style="color: black;">handlers</span>.<span style="color: black;">wsgi</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">if</span> __name__ == <span style="color: #483d8b;">&quot;__main__&quot;</span>:
    <span style="color: #808080; font-style: italic;"># Setup paths - a bit hackish, but works for me.</span>
    <span style="color: #808080; font-style: italic;"># Assumes an absolute path is stored in &lt;project&gt;.local_settings.ROOT</span>
    <span style="color: #dc143c;">sys</span>.<span style="color: black;">path</span>.<span style="color: black;">append</span><span style="color: black;">&#40;</span><span style="color: #dc143c;">os</span>.<span style="color: black;">path</span>.<span style="color: black;">realpath</span><span style="color: black;">&#40;</span><span style="color: #dc143c;">os</span>.<span style="color: black;">path</span>.<span style="color: black;">dirname</span><span style="color: black;">&#40;</span>__file__<span style="color: black;">&#41;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">from</span> foo.<span style="color: black;">local_settings</span> <span style="color: #ff7700;font-weight:bold;">import</span> ROOT
    <span style="color: #dc143c;">sys</span>.<span style="color: black;">path</span>.<span style="color: black;">append</span><span style="color: black;">&#40;</span>ROOT<span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #808080; font-style: italic;"># Startup Django</span>
    <span style="color: #dc143c;">os</span>.<span style="color: black;">environ</span><span style="color: black;">&#91;</span><span style="color: #483d8b;">'DJANGO_SETTINGS_MODULE'</span><span style="color: black;">&#93;</span> = <span style="color: #483d8b;">'foo.settings'</span>
    server = wsgiserver.<span style="color: black;">CherryPyWSGIServer</span><span style="color: black;">&#40;</span>
        <span style="color: black;">&#40;</span><span style="color: #483d8b;">'0.0.0.0'</span>, <span style="color: #ff4500;">8888</span><span style="color: black;">&#41;</span>,  <span style="color: #808080; font-style: italic;"># Use '127.0.0.1' to only bind to the localhost</span>
        django.<span style="color: black;">core</span>.<span style="color: black;">handlers</span>.<span style="color: black;">wsgi</span>.<span style="color: black;">WSGIHandler</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
    <span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">try</span>:
        server.<span style="color: black;">start</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">except</span> <span style="color: #008000;">KeyboardInterrupt</span>:
        <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">'Stopping'</span>
        server.<span style="color: black;">stop</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span></pre></div></div>

<p>I also went with the latest stable version of CherryPy&#8217;s wsgiserver instead of checking out trunk like Eric&#8217;s post suggested.</p>
<p>Then I just enabled <code>mod_proxy</code> in Apache and setup the following VirtualHost:</p>

<div class="wp_syntax"><div class="code"><pre class="apache" style="font-family:monospace;">&lt;<span style="color: #000000; font-weight:bold;">Proxy</span> *&gt;
    <span style="color: #00007f;">Order</span> <span style="color: #00007f;">allow</span>,<span style="color: #00007f;">deny</span>
    <span style="color: #00007f;">Allow</span> from <span style="color: #0000ff;">all</span>
&lt;/<span style="color: #000000; font-weight:bold;">Proxy</span>&gt;
&lt;<span style="color: #000000; font-weight:bold;">Location</span> <span style="color: #7f007f;">&quot;/&quot;</span>&gt;
    <span style="color: #00007f;">ProxyPass</span> http://127.0.0.1:<span style="color: #ff0000;">8888</span>/
    <span style="color: #00007f;">ProxyPassReverse</span> http://127.0.0.1:<span style="color: #ff0000;">8888</span>/
&lt;/<span style="color: #000000; font-weight:bold;">Location</span>&gt;</pre></div></div>

<p>If you&#8217;re cool you&#8217;ll write some sort of system specific script to launch your web app on boot.  In a pinch, you can always use a crontab:</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">@</span>reboot <span style="color: #000000; font-weight: bold;">/</span>usr<span style="color: #000000; font-weight: bold;">/</span>bin<span style="color: #000000; font-weight: bold;">/</span>python <span style="color: #000000; font-weight: bold;">/</span>path<span style="color: #000000; font-weight: bold;">/</span>to<span style="color: #000000; font-weight: bold;">/</span>app.py <span style="color: #000000; font-weight: bold;">&amp;</span></pre></div></div>

<p>YMMV <img src='http://blog.schmichael.com/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' /> </p>
<p><small><br />
* To mod_wsgi&#8217;s credit, it took about 10 seconds to compile, generated a Universal binary, and in general Just Worked.</p>
<p>** I&#8217;m already a CherryPy fan thanks to <a href="http://www.dowski.com/">dowski</a>, so it wasn&#8217;t a hard decision.<br />
</small></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.schmichael.com/2009/02/18/deploying-django-with-cherrypy/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Web Server Quandary</title>
		<link>http://blog.schmichael.com/2008/12/27/web-server-quandary/</link>
		<comments>http://blog.schmichael.com/2008/12/27/web-server-quandary/#comments</comments>
		<pubDate>Sat, 27 Dec 2008 07:00:48 +0000</pubDate>
		<dc:creator>Michael Schurter</dc:creator>
				<category><![CDATA[GNU/Linux]]></category>
		<category><![CDATA[Open Source]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[Technology]]></category>
		<category><![CDATA[apache]]></category>
		<category><![CDATA[cherokee]]></category>
		<category><![CDATA[lazyweb]]></category>
		<category><![CDATA[lighttpd]]></category>
		<category><![CDATA[nginx]]></category>

		<guid isPermaLink="false">http://michael.susens-schurter.com/blog/?p=469</guid>
		<description><![CDATA[Apache was probably the first Linux application I learned how to configure. However, I&#8217;ve gotten a bit frustrated with it recently&#8230; The Problem A memory leak. Apache is eating up memory so quickly that I need to restart it every &#8230; <a href="http://blog.schmichael.com/2008/12/27/web-server-quandary/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p><a href="http://httpd.apache.org/">Apache</a> was probably the first Linux application I learned how to configure.  However, I&#8217;ve gotten a bit frustrated with it recently&#8230;</p>
<p><strong>The Problem</strong></p>
<p><em>A memory leak.</em>  Apache is eating up memory so quickly that I need to restart it every couple days or risk my entire server grinding to a halt as it starts swapping wildly.  I&#8217;ve poured over log files and <code>pmap</code> output, but I still can&#8217;t figure out where the problem lies.  Curse you monolithic in-process architecture!</p>
<p>Actually I know what my problem is, I&#8217;m running a mess of modules:</p>
<ul>
<li><code>ssl</code> &#8211; 2 certificates on 2 ports</li>
<li><code>php5</code> &#8211; blerg, who doesn&#8217;t have to run this?</li>
<li><code>suphp</code> &#8211; I suspect this is my problem, but I can&#8217;t prove it.  A client&#8217;s 3rd party web application <em>requires</em> it, but I think its easily replaceable with FastCGI.</li>
<li><code>wsgi</code> &#8211; No complaints.  Python apps are out-of-process thankfully.</li>
<li><code>proxy</code> &#8211; Again no complaints.  Can&#8217;t imagine how this module could cause any problems except it does proxy some large (multi-megabyte, not huge) POSTs at times.  I can&#8217;t imagine a memory leak could slip into this module without a lot of people noticing.</li>
</ul>
<p><strong>Solution A: Apache+FastCGI</strong></p>
<p>I love the idea of putting each web application in its own process and letting Apache just act as an HTTP router.  FastCGI seems to have all the features I need, and I&#8217;m not really worried about the CPU overhead incurred by IPC.</p>
<p>However, there are 2 competing FastCGI modules for Apache, and I have no idea what to choose.  Anecdotally the official <a href="http://www.fastcgi.com/drupal/node/3">mod_fastcgi</a> is buggy and <a href="http://www.fastcgi.com/drupal/node/2">fastcgi.com is a spam infested wasteland</a>.  However, I&#8217;ve found no authoritative source saying:<em> &#8220;fastcgi is dead, long live <a href="http://fastcgi.coremail.cn/">fcgid</a>!&#8221;</em>  (Lame excuse, I know.)</p>
<p><strong>Solution B: <a href="http://www.lighttpd.net/">Lighttpd</a></strong></p>
<p>I know Lighty is the darling of Rails sites, but whenever I stop by its site I&#8217;m greeted with a list of recently fixed <a href="http://cve.mitre.org/cgi-bin/cvekey.cgi?keyword=lighttpd">security bugs</a>, and now it seems as though <a href="http://blog.lighttpd.net/articles/2008/12/02/a-little-heads-up">they&#8217;re rewriting the core</a>!</p>
<p>I&#8217;m sure Lighty is a high quality intelligently engineered project, but it seems to be the definition of immature.  Not necessarily bad (in fact it usually means its progressing quickly!), but perhaps not as reliable as good old workhorses like Apache.</p>
<p><strong>Solution C: <a href="http://www.cherokee-project.com/">Cherokee</a></strong></p>
<p>I&#8217;ve been following Cherokee for some time now and running it locally on my workstation.  I <em>love</em> the web interface.  I&#8217;m usually a very anti-webmin, pro-vim kind of guy, but I&#8217;m sick of editing Apache&#8217;s config files.  I do it about once a month and therefore it always takes lots of double-checking the docs.  I don&#8217;t know why, but its configuration has just never felt natural to me.</p>
<p>However, the lead Cherokee developer&#8217;s bravado is by the most off-putting aspect of the project.  <a href="http://lists.octality.com/pipermail/cherokee/2008-December/009437.html">He mocks modwsgi</a> and posts simplistic benchmarks showing Cherokee to be the fastest web server, but meanwhile Cherokee churns out numerous bug patch releases in-between feature releases and has yet to reach 1.0 status.</p>
<p>It seems like an excellent project technically, but I&#8217;m afraid there will be negative consequences for the lead developers hubris.  <small>(I&#8217;m not meaning to insult the guy.  He&#8217;s probably a far better hacker than I&#8217;ll ever be.  Self-promotion just makes me uncomfortable.)</small></p>
<p><strong>Solution D: <a href="http://nginx.net/">nginx</a></strong></p>
<p>I don&#8217;t know much about nginx except that it works.  Basically all I&#8217;ve heard about it is:</p>
<ul>
<li>It works.</li>
<li>Its fast.  <em>Really</em> fast.</li>
</ul>
<p>While &#8220;working&#8221; is definitely my primary objective, nginx seems a bit bare bones for me.  I just don&#8217;t think I&#8217;m the target demographic.  I&#8217;d kind of like for my web server to handle spawning and kill of FastCGI processes.</p>
<p>nginx feels like git to me.  Those who know it: use it and love it.  Those who don&#8217;t: stand in fear and awe of its unbridled power.</p>
<p>&#8230;or maybe its just a nice simple barebones HTTP server&#8230;</p>
<p><strong>Conclusions?</strong></p>
<p>I think <strong>Solution A: FastCGI</strong> is the most sensible.  Apache has always served me well, and the memory leak is most likely due to that shoddy suphp module.</p>
<p>Moving my web applications to FastCGI is also the best way to prepare to move to one of these 2nd generation web servers.</p>
<p>However, I&#8217;m getting kind of sick of Apache, and the ambiguousness of which FastCGI solution to choose is fairly annoying.</p>
<p>So dear lazyweb, for your everyday web developer consultant looking to run a bunch of PHP and Python web applications, what HTTP server stack should I use?  (Debian Lenny packages are a plus.)</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.schmichael.com/2008/12/27/web-server-quandary/feed/</wfw:commentRss>
		<slash:comments>20</slash:comments>
		</item>
	</channel>
</rss>

