<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <title>python</title>
  <link rel="alternate" type="text/html" href="http://www.nekomancer.net/taxonomy/term/8"/>
  <link rel="self" type="application/atom+xml" href="http://www.nekomancer.net/taxonomy/term/8/atom/feed"/>
  <id>http://www.nekomancer.net/taxonomy/term/8/atom/feed</id>
  <updated>2008-06-27T03:41:12-05:00</updated>
  <entry>
    <title>google app engine: from sql to excel</title>
    <link rel="alternate" type="text/html" href="http://www.nekomancer.net/blog/2008/04/13/google-appengine-sql-excel" />
    <id>http://www.nekomancer.net/blog/2008/04/13/google-appengine-sql-excel</id>
    <published>2008-04-13T15:52:12-05:00</published>
    <updated>2008-05-14T13:54:18-05:00</updated>
    <author>
      <name>gabor</name>
    </author>
    <category term="python" />
    <category term="programming" />
    <summary type="html"><![CDATA[<p>As many other people, i also got my google app account (even crateated a <a href="http://viewrequest.appspot.com">stupid test application</a>. it&#8217;s fun to try out such a radically different hosting-environment.</p>

<p>but there is an issue with it seems many do not realize:</p>

<p>the &#8220;database&#8221; backend of google-app-engine (i will call it <a href="http://en.wikipedia.org/wiki/Bigtable">BigTable</a> in the following text) is not a relational (read &#8220;SQL&#8221;) store, and it will never be. for example, it does not support SQL JOINs. but it&#8217;s worse than that. because of it&#8217;s architecture, JOINS will never be fast there. BigTable is essentially a collection of spreadsheet-tables, where you can do some basic searches, that&#8217;s all. oh, and transactions.</p>

<p>for this reason, there probably never will be a BigTable django-ORM wrapper. of course technically it&#8217;s possible to implement in python all the missing features, but it&#8217;s performance characteristics will not be the same as of a relational-database.</p>
    ]]></summary>
    <content type="html"><![CDATA[<p>As many other people, i also got my google app account (even crateated a <a href="http://viewrequest.appspot.com">stupid test application</a>. it&#8217;s fun to try out such a radically different hosting-environment.</p>

<p>but there is an issue with it seems many do not realize:</p>

<p>the &#8220;database&#8221; backend of google-app-engine (i will call it <a href="http://en.wikipedia.org/wiki/Bigtable">BigTable</a> in the following text) is not a relational (read &#8220;SQL&#8221;) store, and it will never be. for example, it does not support SQL JOINs. but it&#8217;s worse than that. because of it&#8217;s architecture, JOINS will never be fast there. BigTable is essentially a collection of spreadsheet-tables, where you can do some basic searches, that&#8217;s all. oh, and transactions.</p>

<p>for this reason, there probably never will be a BigTable django-ORM wrapper. of course technically it&#8217;s possible to implement in python all the missing features, but it&#8217;s performance characteristics will not be the same as of a relational-database. so you will not be able to simply take your mysql/postgresql-optimized application, and deploy on it, and all is fine. you will have to restructure your application.</p>

<p>and if you have to restructure your app anyway, why do you need the django-ORM? you can as well write google-app-engine-specific code.</p>

<p>(on the other hand, maybe there could be a more stupid django-orm, that does not assume a relational-db-backend, and it could work with the various non-relational databases like <a href="http://en.wikipedia.org/wiki/Bigtable">BigTable</a> or <a href="http://hadoop.apache.org/hbase/">hBase</a> or other <a href="http://en.wikipedia.org/wiki/Column-oriented_DBMS">column-oriented databases</a>&#8230;)</p>

<p>the basic idea when writing BigTable code is that read-operations will happen much more often than write-operations. so do more at write-time, and less at read-time. denormalize tables.</p>

<p>for example, take a simple forum-application. it stores discussions. a discussion has comments.
now let&#8217;s see how we could implement 2 basic features: &#8220;add comment&#8221; and &#8220;list discussion-names with comment-count&#8221;.</p>

<p>SQL:</p>

<ul>
<li>&#8220;add comment&#8221;: store a new comment-entry, which contains a link (a foreign-key) to it&#8217;s discussion</li>
<li>&#8220;list discussion-names with comment-count&#8221;: do an SQL query like: <span class="geshifilter"><code class="geshifilter-text">SELECT discussion.name,count(1) from discussion LEFT OUTER JOIN comment GROUP BY comment.discussion_id;</code></span> (let&#8217;s not discuss right now if it&#8217;s inner or outer join etc. it&#8217;s quite late at night here, so maybe it&#8217;s not 100% correct. but it should be enough to demonstrate the situation)</li>
</ul>

<p>BigTable (one possible solution):</p>

<ul>
<li>&#8220;add comment&#8221;: store a new comment entry, which contains a link to it&#8217;s discussion. also, count the number of comments for this discussion, and store this value in the discussion-table</li>
<li>&#8220;list discussion-names with comment-count&#8221;: <span class="geshifilter"><code class="geshifilter-text">select * from discussion</code></span></li>
</ul>

<p>of course the whole denormalize-your-database-if-you-want-performance mantra is nothing new. if i remember correctly, Flickr also does this. but still, for most developers, (also for me), it&#8217;s just painful to give up our nice, clean, normalized db-tables.</p>

<p>p.s: please note, that all the info is not based on my own performance-benchmarks. it&#8217;s more a summary of what i&#8217;ve read in the the google-appengine documentation and the <a href="http://groups.google.com/group/google-appengine">google-appengine mailing list</a>.</p>
    ]]></content>
  </entry>
  <entry>
    <title>python web-application using generators</title>
    <link rel="alternate" type="text/html" href="http://www.nekomancer.net/blog/archives/python-web-app-using-generators" />
    <id>http://www.nekomancer.net/blog/archives/python-web-app-using-generators</id>
    <published>2008-03-01T17:16:16-06:00</published>
    <updated>2008-06-27T03:41:12-05:00</updated>
    <author>
      <name>gabor</name>
    </author>
    <category term="python" />
    <category term="programming" />
    <summary type="html"><![CDATA[<p>Probably many of you have heard already about <a href="http://www.seaside.st/">Seaside</a>. It&#8217;s a smalltalk web framework, where you can write a web-app in a linear style:</p>

<p>let&#8217;s say you want to create a web-app which:</p>

<ul>
<li>shows a form to the user, where he can enter a number and submit it</li>
<li>then you show him a second form, where the user can enter a second number and submit it</li>
<li>then you show the user a page which displays the sum of those 2 submitted numbers</li>
</ul>
    ]]></summary>
    <content type="html"><![CDATA[<p>Probably many of you have heard already about <a href="http://www.seaside.st/">Seaside</a>. It&#8217;s a smalltalk web framework, where you can write a web-app in a linear style:</p>

<p>let&#8217;s say you want to create a web-app which:</p>

<ul>
<li>shows a form to the user, where he can enter a number and submit it</li>
<li>then you show him a second form, where the user can enter a second number and submit it</li>
<li>then you show the user a page which displays the sum of those 2 submitted numbers
<!--break-->
in Seaside, you can implement it in something like this:
(pseudocode)</li>
</ul>

<div class="geshifilter"><pre class="geshifilter-python">first_num = get_number<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
second_num = get_number<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
display<span style="color: black;">&#40;</span>first_num + second_num<span style="color: black;">&#41;</span></pre></div>

<p>my language of choice is python, so i was curious if it&#8217;s possible to achieve something similar in that language. seside uses <a href="http://en.wikipedia.org/wiki/Continuation">continuations</a> to achieve this, so i turned to <a href="http://docs.python.org/ref/yield.html">python generators</a>. they allowed me to write this:</p>

<div class="geshifilter"><pre class="geshifilter-python"><span style="color: #ff7700;font-weight:bold;">def</span> sum_two_numbers<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
    first_num = <span style="color: #ff7700;font-weight:bold;">yield</span> InputPage<span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;enter first number:&quot;</span><span style="color: black;">&#41;</span>
    second_num = <span style="color: #ff7700;font-weight:bold;">yield</span> InputPage<span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;enter second number:&quot;</span><span style="color: black;">&#41;</span>
    <span style="color: #008000;">sum</span> = <span style="color: #008000;">int</span><span style="color: black;">&#40;</span>first_num<span style="color: black;">&#41;</span> + <span style="color: #008000;">int</span><span style="color: black;">&#40;</span>second_num<span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">yield</span> TextPage<span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;the sum isresult is: %s&quot;</span> <span style="color: #66cc66;">%</span> <span style="color: #008000;">sum</span><span style="color: black;">&#41;</span></pre></div>

<p>the full code is below, but first some notes about it:</p>

<ul>
<li>it requires python 2.5 or higher, because i use the <a href="http://docs.python.org/whatsnew/pep-342.html">&#8220;advanced&#8221; version of yield</a>, which appeared in python2.5</li>
<li>this is only proof-of-concept code, and i know that it uses global-variables, ugly names, get-where-it-should-do-post etc.</li>
<li>i know Seaside does much much more (backbutton-support etc.)</li>
</ul>

<p>the code:</p>

<div class="geshifilter"><pre class="geshifilter-python"><span style="color: #808080; font-style: italic;">#!/usr/bin/env python2.5</span>
<span style="color: #ff7700;font-weight:bold;">from</span> wsgiref.<span style="color: black;">simple_server</span> <span style="color: #ff7700;font-weight:bold;">import</span> make_server
<span style="color: #ff7700;font-weight:bold;">from</span> <span style="color: #dc143c;">cgi</span> <span style="color: #ff7700;font-weight:bold;">import</span> parse_qs
&nbsp;
&nbsp;
<span style="color: #ff7700;font-weight:bold;">class</span> TextPage<span style="color: black;">&#40;</span><span style="color: #008000;">object</span><span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">def</span> <span style="color: #0000cd;">__init__</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>,text<span style="color: black;">&#41;</span>:
        <span style="color: #008000;">self</span>.<span style="color: black;">text</span> = text
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> get_response_content<span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>:
        <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #483d8b;">'&lt;html&gt;&lt;body&gt;%s&lt;/body&gt;&lt;/html&gt;'</span> <span style="color: #66cc66;">%</span> <span style="color: #008000;">self</span>.<span style="color: black;">text</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> get_request_data<span style="color: black;">&#40;</span><span style="color: #008000;">self</span>,environ<span style="color: black;">&#41;</span>:
        <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #008000;">None</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">class</span> InputPage<span style="color: black;">&#40;</span>TextPage<span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">def</span> get_response_content<span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>:
        <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #483d8b;">&quot;&quot;</span><span style="color: #483d8b;">&quot;&lt;html&gt;&lt;body&gt;%s
            &lt;form method=&quot;</span>get<span style="color: #483d8b;">&quot; action=&quot;</span>.<span style="color: #483d8b;">&quot;&gt;
            &lt;input type=&quot;</span>text<span style="color: #483d8b;">&quot; name=&quot;</span>data<span style="color: #483d8b;">&quot; value=&quot;</span><span style="color: #483d8b;">&quot;/&gt;
            &lt;/form&gt;
            &lt;/body&gt;&lt;/html&gt;&quot;</span><span style="color: #483d8b;">&quot;&quot;</span> <span style="color: #66cc66;">%</span> <span style="color: #008000;">self</span>.<span style="color: black;">text</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> get_request_data<span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, environ<span style="color: black;">&#41;</span>:
        get_req_dict = parse_qs<span style="color: black;">&#40;</span>environ<span style="color: black;">&#91;</span><span style="color: #483d8b;">'QUERY_STRING'</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span>
        <span style="color: #ff7700;font-weight:bold;">return</span> get_req_dict<span style="color: black;">&#91;</span><span style="color: #483d8b;">'data'</span><span style="color: black;">&#93;</span><span style="color: black;">&#91;</span><span style="color: #ff4500;">0</span><span style="color: black;">&#93;</span>
&nbsp;
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> sum_two_numbers<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
    first_num = <span style="color: #ff7700;font-weight:bold;">yield</span> InputPage<span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;enter first number:&quot;</span><span style="color: black;">&#41;</span>
    second_num = <span style="color: #ff7700;font-weight:bold;">yield</span> InputPage<span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;enter second number:&quot;</span><span style="color: black;">&#41;</span>
    <span style="color: #008000;">sum</span> = <span style="color: #008000;">int</span><span style="color: black;">&#40;</span>first_num<span style="color: black;">&#41;</span> + <span style="color: #008000;">int</span><span style="color: black;">&#40;</span>second_num<span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">yield</span> TextPage<span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;the sum isresult is: %s&quot;</span> <span style="color: #66cc66;">%</span> <span style="color: #008000;">sum</span><span style="color: black;">&#41;</span>
&nbsp;
s = sum_two_numbers<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
cur_item = <span style="color: #008000;">None</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> simple_app<span style="color: black;">&#40;</span>environ, start_response<span style="color: black;">&#41;</span>:
    status = <span style="color: #483d8b;">'200 OK'</span>
    response_headers = <span style="color: black;">&#91;</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'Content-type'</span>,<span style="color: #483d8b;">'text/html'</span><span style="color: black;">&#41;</span><span style="color: black;">&#93;</span>
    start_response<span style="color: black;">&#40;</span>status, response_headers<span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">global</span> cur_item
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #ff7700;font-weight:bold;">not</span> cur_item:
        cur_item = s.<span style="color: black;">next</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">else</span>:
        cur_item = s.<span style="color: black;">send</span><span style="color: black;">&#40;</span>cur_item.<span style="color: black;">get_request_data</span><span style="color: black;">&#40;</span>environ<span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: black;">&#91;</span>cur_item.<span style="color: black;">get_response_content</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><span style="color: black;">&#93;</span>
&nbsp;
&nbsp;
httpd = make_server<span style="color: black;">&#40;</span><span style="color: #483d8b;">''</span>, <span style="color: #ff4500;">8000</span>, simple_app<span style="color: black;">&#41;</span>
httpd.<span style="color: black;">serve_forever</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span></pre></div>

<p>i did a quick google-check about this topic (&#8220;python web framework continuations&#8221;), and only found <a href="http://twistedmatrix.com/pipermail/twisted-web/2004-November/000863.html">Nevow with Wolf</a>, which uses a less-elegant approach, probably because when it was implemented, python2.5 was not yet available. if anyone knows about other python web-frameworks that use generators, leave me a comment.</p>
    ]]></content>
  </entry>
</feed>
