<?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/"
	xmlns:georss="http://www.georss.org/georss" xmlns:geo="http://www.w3.org/2003/01/geo/wgs84_pos#" xmlns:media="http://search.yahoo.com/mrss/"
	>

<channel>
	<title>App Engine</title>
	<atom:link href="http://appengineua.wordpress.com/feed/" rel="self" type="application/rss+xml" />
	<link>http://appengineua.wordpress.com</link>
	<description>или как я перестал волноваться и полюбил атомную бомбу</description>
	<lastBuildDate>Mon, 13 Dec 2010 11:14:48 +0000</lastBuildDate>
	<language>ru</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.com/</generator>
<cloud domain='appengineua.wordpress.com' port='80' path='/?rsscloud=notify' registerProcedure='' protocol='http-post' />
<image>
		<url>http://1.gravatar.com/blavatar/1af83cf7f11384f19cdde63789c59e80?s=96&#038;d=http%3A%2F%2Fs2.wp.com%2Fi%2Fbuttonw-com.png</url>
		<title>App Engine</title>
		<link>http://appengineua.wordpress.com</link>
	</image>
	<atom:link rel="search" type="application/opensearchdescription+xml" href="http://appengineua.wordpress.com/osd.xml" title="App Engine" />
	<atom:link rel='hub' href='http://appengineua.wordpress.com/?pushpress=hub'/>
		<item>
		<title>Оптимизация сортировки в таблицах с текстовыми полями</title>
		<link>http://appengineua.wordpress.com/2010/11/16/filesort-elimination/</link>
		<comments>http://appengineua.wordpress.com/2010/11/16/filesort-elimination/#comments</comments>
		<pubDate>Tue, 16 Nov 2010 12:43:11 +0000</pubDate>
		<dc:creator>dchaplinsky</dc:creator>
				<category><![CDATA[ORM]]></category>
		<category><![CDATA[django]]></category>
		<category><![CDATA[filesort]]></category>
		<category><![CDATA[optimization]]></category>
		<category><![CDATA[orm]]></category>

		<guid isPermaLink="false">http://appengine.com.ua/?p=63</guid>
		<description><![CDATA[Проблема с сабжем в том, что mysql сортирует сначала все выбранные данные, а потом отдает кусочек, который ты указал в limit. Соответстветственно, даже при наличии индекса по полю сортировки он выпадает в filesort если в таблице есть крупные поля. Обычный подход состоит в том, чтобы сделать задуманое двумя запросами: первым (легким) выгрести только id отсортированных [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=appengineua.wordpress.com&amp;blog=9983379&amp;post=63&amp;subd=appengineua&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>Проблема с сабжем в том, что mysql сортирует сначала все выбранные данные, а потом отдает кусочек, который ты указал в limit. Соответстветственно, даже при наличии индекса по полю сортировки он выпадает в filesort если в таблице есть крупные поля.</p>
<p>Обычный подход состоит в том, чтобы сделать задуманое двумя запросами: первым (легким) выгрести только id отсортированных записей и избежать filesort, а вторым уже получить полные записи для этих id.</p>
<p>Ну, например, вот так:</p>
<pre style='color:#000000;background:#ffffff;'><span style='color:#800000;font-weight:bold;'>class</span> FoobarManager<span style='color:#808030;'>(</span>models<span style='color:#808030;'>.</span>Manager<span style='color:#808030;'>)</span><span style='color:#808030;'>:</span>
    <span style='color:#800000;font-weight:bold;'>def</span> latest<span style='color:#808030;'>(</span>self<span style='color:#808030;'>,</span> limit<span style='color:#808030;'>=</span><span style='color:#008c00;'>10</span><span style='color:#808030;'>)</span><span style='color:#808030;'>:</span>
        <span style='color:#696969;'>""" more effecient version of query to avoid filesort """</span>
        ids <span style='color:#808030;'>=</span> <span style='color:#e34adc;'>list</span><span style='color:#808030;'>(</span>self<span style='color:#808030;'>.</span>values_list<span style='color:#808030;'>(</span><span style='color:#0000e6;'>'id'</span><span style='color:#808030;'>,</span> flat<span style='color:#808030;'>=</span><span style='color:#e34adc;'>True</span><span style='color:#808030;'>)</span><span style='color:#808030;'>.</span>order_by<span style='color:#808030;'>(</span><span style='color:#0000e6;'>'-modified'</span><span style='color:#808030;'>)</span><span style='color:#808030;'>[</span><span style='color:#808030;'>:</span>limit<span style='color:#808030;'>]</span><span style='color:#808030;'>)</span>

        <span style='color:#800000;font-weight:bold;'>return</span> self<span style='color:#808030;'>.</span><span style='color:#e34adc;'>filter</span><span style='color:#808030;'>(</span>id__in<span style='color:#808030;'>=</span>ids<span style='color:#808030;'>)</span><span style='color:#808030;'>.</span>extra<span style='color:#808030;'>(</span>
                select<span style='color:#808030;'>=</span><span style='color:#800080;'>{</span><span style='color:#0000e6;'>'manual'</span><span style='color:#808030;'>:</span> <span style='color:#0000e6;'>'FIELD(id,%s)'</span> <span style='color:#808030;'>%</span> <span style='color:#0000e6;'>','</span><span style='color:#808030;'>.</span>join<span style='color:#808030;'>(</span><span style='color:#e34adc;'>map</span><span style='color:#808030;'>(</span><span style='color:#e34adc;'>str</span><span style='color:#808030;'>,</span> ids<span style='color:#808030;'>)</span><span style='color:#808030;'>)</span><span style='color:#800080;'>}</span><span style='color:#808030;'>,</span>
                order_by<span style='color:#808030;'>=</span><span style='color:#808030;'>[</span><span style='color:#0000e6;'>'manual'</span><span style='color:#808030;'>]</span><span style='color:#808030;'>)</span>
</pre>
<p>Идея насчет реализации order_by(&#8216;manual&#8217;) взята <a href="http://davedash.com/2010/02/11/retrieving-elements-in-a-specific-order-in-django-and-mysql/">отсюда</a>, а сама необходимость в нем описана вот <a href="http://sphinxsearch.com/info/faq/#row-storage">тут</a>.<br />
Можно не делать order_by(&#8216;manual&#8217;), а сделать повторный order_by(&#8216;-modified&#8217;) при желании. По идее, производительность не пострадает.</p>
<p>Второй способ решения этой проблемы — вынос больших текстовых полей в отдельную таблицу, выбирать из которой можно по связке one2one.<br />
В связи с этим возникает идея использовать <a href="http://docs.djangoproject.com/en/dev/topics/db/models/#multi-table-inheritance">Django MultiTable Inheritance</a> и класть в таблицу предка мелкие поля, в наследника — крупные, а уж запрос Django ORM должен и сам сгенерировать довольно оптимальный. Как–то оно попрозрачнее получится. Надо попробовать, короче</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/appengineua.wordpress.com/63/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/appengineua.wordpress.com/63/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/appengineua.wordpress.com/63/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/appengineua.wordpress.com/63/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/appengineua.wordpress.com/63/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/appengineua.wordpress.com/63/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/appengineua.wordpress.com/63/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/appengineua.wordpress.com/63/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/appengineua.wordpress.com/63/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/appengineua.wordpress.com/63/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/appengineua.wordpress.com/63/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/appengineua.wordpress.com/63/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/appengineua.wordpress.com/63/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/appengineua.wordpress.com/63/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=appengineua.wordpress.com&amp;blog=9983379&amp;post=63&amp;subd=appengineua&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://appengineua.wordpress.com/2010/11/16/filesort-elimination/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/19b55cc85f95bbd78de4dc9d798f663a?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">dchaplinsky</media:title>
		</media:content>
	</item>
		<item>
		<title>Цветной logger</title>
		<link>http://appengineua.wordpress.com/2010/10/30/colorful-logger/</link>
		<comments>http://appengineua.wordpress.com/2010/10/30/colorful-logger/#comments</comments>
		<pubDate>Fri, 29 Oct 2010 23:00:31 +0000</pubDate>
		<dc:creator>dchaplinsky</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[useful]]></category>

		<guid isPermaLink="false">http://appengine.com.ua/?p=64</guid>
		<description><![CDATA[Тут. Сейчас и опробую.<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=appengineua.wordpress.com&amp;blog=9983379&amp;post=64&amp;subd=appengineua&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p><a href="http://stackoverflow.com/questions/384076/how-can-i-make-the-python-logging-output-to-be-colored">Тут</a>.</p>
<p>Сейчас и опробую.</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/appengineua.wordpress.com/64/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/appengineua.wordpress.com/64/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/appengineua.wordpress.com/64/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/appengineua.wordpress.com/64/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/appengineua.wordpress.com/64/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/appengineua.wordpress.com/64/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/appengineua.wordpress.com/64/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/appengineua.wordpress.com/64/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/appengineua.wordpress.com/64/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/appengineua.wordpress.com/64/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/appengineua.wordpress.com/64/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/appengineua.wordpress.com/64/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/appengineua.wordpress.com/64/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/appengineua.wordpress.com/64/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=appengineua.wordpress.com&amp;blog=9983379&amp;post=64&amp;subd=appengineua&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://appengineua.wordpress.com/2010/10/30/colorful-logger/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/19b55cc85f95bbd78de4dc9d798f663a?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">dchaplinsky</media:title>
		</media:content>
	</item>
		<item>
		<title>hg externals</title>
		<link>http://appengineua.wordpress.com/2010/04/11/hg-externals/</link>
		<comments>http://appengineua.wordpress.com/2010/04/11/hg-externals/#comments</comments>
		<pubDate>Sun, 11 Apr 2010 21:56:58 +0000</pubDate>
		<dc:creator>dchaplinsky</dc:creator>
				<category><![CDATA[Общая информация]]></category>
		<category><![CDATA[hg]]></category>

		<guid isPermaLink="false">http://appengine.com.ua/?p=60</guid>
		<description><![CDATA[hg externals — удобное маленькое расширение для scm mercurial. Позволяет примапить папки внутри рабочей копии к другим репозитариям (аналог svn externals). Помимо hg поддерживает еще и svn. Имеет смысл, допустим, если вы используете какие–то внешние библиотеки в рамках проекта и хотите постоянно поддерживать их в максимально свежем состоянии, или у вас несколько проектов, с общими [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=appengineua.wordpress.com&amp;blog=9983379&amp;post=60&amp;subd=appengineua&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p><a href="http://pypi.python.org/pypi/hgexternals/">hg externals</a> — удобное маленькое расширение для scm mercurial. Позволяет примапить папки внутри рабочей копии к другим репозитариям (аналог <a href="http://svnbook.red-bean.com/en/1.0/ch07s03.html">svn externals</a>). Помимо hg поддерживает еще и svn.</p>
<p>Имеет смысл, допустим, если вы используете какие–то внешние библиотеки в рамках проекта и хотите постоянно поддерживать их в максимально свежем состоянии, или у вас несколько проектов, с общими кусками, которые целесообразно вынести в отдельные репозитарии.</p>
<p>Молча ставится из исходников на любой меркуриал, но работает нормально только с 1.5 :)</p>
<p>Кстати, selenic наконец обновил сайт для <a href="http://mercurial.selenic.com/">mercurial</a>, куда катится этот мир?</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/appengineua.wordpress.com/60/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/appengineua.wordpress.com/60/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/appengineua.wordpress.com/60/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/appengineua.wordpress.com/60/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/appengineua.wordpress.com/60/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/appengineua.wordpress.com/60/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/appengineua.wordpress.com/60/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/appengineua.wordpress.com/60/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/appengineua.wordpress.com/60/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/appengineua.wordpress.com/60/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/appengineua.wordpress.com/60/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/appengineua.wordpress.com/60/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/appengineua.wordpress.com/60/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/appengineua.wordpress.com/60/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=appengineua.wordpress.com&amp;blog=9983379&amp;post=60&amp;subd=appengineua&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://appengineua.wordpress.com/2010/04/11/hg-externals/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/19b55cc85f95bbd78de4dc9d798f663a?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">dchaplinsky</media:title>
		</media:content>
	</item>
		<item>
		<title>Удаление всех записей из таблицы.</title>
		<link>http://appengineua.wordpress.com/2009/11/23/kill-them-all/</link>
		<comments>http://appengineua.wordpress.com/2009/11/23/kill-them-all/#comments</comments>
		<pubDate>Mon, 23 Nov 2009 02:04:38 +0000</pubDate>
		<dc:creator>dchaplinsky</dc:creator>
				<category><![CDATA[Общая информация]]></category>
		<category><![CDATA[bigtable]]></category>
		<category><![CDATA[gae]]></category>
		<category><![CDATA[gql]]></category>
		<category><![CDATA[wtf]]></category>

		<guid isPermaLink="false">http://appengine.com.ua/?p=58</guid>
		<description><![CDATA[Удивительное рядом: db.delete(Score.all()) исполняется на полторы секунды ДОЛЬШЕ чем лобовой способ: for score in Score.all(): score.delete() На датасете из 1000 элементов в локальном варианте GAE. Я бы подумал, что это флюктуация, но результат воспроизводится с завидным постоянством.<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=appengineua.wordpress.com&amp;blog=9983379&amp;post=58&amp;subd=appengineua&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>Удивительное рядом:</p>
<pre><code>           db.delete(Score.all())</code></pre>
<p>исполняется на полторы секунды <strong>ДОЛЬШЕ</strong> чем лобовой способ:</p>
<pre><code>
             for score in Score.all():
                 score.delete()
</code></pre>
<p>На датасете из 1000 элементов в локальном варианте GAE. Я бы подумал, что это флюктуация, но результат воспроизводится с завидным постоянством.</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/appengineua.wordpress.com/58/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/appengineua.wordpress.com/58/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/appengineua.wordpress.com/58/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/appengineua.wordpress.com/58/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/appengineua.wordpress.com/58/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/appengineua.wordpress.com/58/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/appengineua.wordpress.com/58/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/appengineua.wordpress.com/58/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/appengineua.wordpress.com/58/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/appengineua.wordpress.com/58/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/appengineua.wordpress.com/58/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/appengineua.wordpress.com/58/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/appengineua.wordpress.com/58/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/appengineua.wordpress.com/58/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=appengineua.wordpress.com&amp;blog=9983379&amp;post=58&amp;subd=appengineua&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://appengineua.wordpress.com/2009/11/23/kill-them-all/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/19b55cc85f95bbd78de4dc9d798f663a?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">dchaplinsky</media:title>
		</media:content>
	</item>
		<item>
		<title>Поиск строк по префиксу в BigTable</title>
		<link>http://appengineua.wordpress.com/2009/11/23/prefix-trick/</link>
		<comments>http://appengineua.wordpress.com/2009/11/23/prefix-trick/#comments</comments>
		<pubDate>Mon, 23 Nov 2009 00:13:13 +0000</pubDate>
		<dc:creator>dchaplinsky</dc:creator>
				<category><![CDATA[Общая информация]]></category>
		<category><![CDATA[bigtable]]></category>
		<category><![CDATA[datastore]]></category>
		<category><![CDATA[gae]]></category>
		<category><![CDATA[gql]]></category>

		<guid isPermaLink="false">http://appengine.com.ua/?p=55</guid>
		<description><![CDATA[Нативный GAE дэйтастор не умеет фильтровать строки по префиксу, как это делает, например mysql SELECT * FROM foo WHERE bar LIKE 'prefix%'; Взамен этого в мануале предлагается следущий трюк: db.GqlQuery("SELECT * FROM foo WHERE bar &#62;= :1 AND bar &#60; :2&#34;, &#34;prefix&#34;, u&#34;prefix&#34; + u&#34;\ufffd&#34;) То есть, выбрать все значения которые лежат между префиксом и [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=appengineua.wordpress.com&amp;blog=9983379&amp;post=55&amp;subd=appengineua&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>Нативный GAE дэйтастор не умеет фильтровать строки по префиксу, как это делает, например mysql </p>
<pre><code>SELECT * FROM foo WHERE bar LIKE 'prefix%';</code></pre>
<p>Взамен этого в <a href="http://code.google.com/appengine/docs/python/datastore/queriesandindexes.html#Introducing_Indexes">мануале</a> предлагается следущий трюк:</p>
<pre><code>db.GqlQuery("SELECT * FROM foo WHERE bar &gt;= :1 AND bar &lt; :2&quot;,
 &quot;prefix&quot;, u&quot;prefix&quot; + u&quot;\ufffd&quot;)</code></pre>
<p>То есть, выбрать все значения которые лежат между префиксом и префиксом + наибольший unicode символ. В отсортированом по этому полю дэйтасете это даст как раз выборку по префиксу.</p>
<p>Учитывая, что он создает индексы для подобных выборок автоматически, должно быть довольно быстро.</p>
<p>Трюк, конечно, из разряда удаления гланд через анус (кроме того, непонятно, как матчить строки по постфиксу, или просто по вхождению), с другой стороны, надо попробовать такое в MySQL, может побыстрее нэйтивного лайка будет. Хотя, не исключено, что он именно так и реализован внутренне :).</p>
<p>Stay tuned, сегодня–завтра будет пост по расчетам медиан на крупных выборках с профайлингом и т.п.</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/appengineua.wordpress.com/55/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/appengineua.wordpress.com/55/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/appengineua.wordpress.com/55/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/appengineua.wordpress.com/55/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/appengineua.wordpress.com/55/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/appengineua.wordpress.com/55/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/appengineua.wordpress.com/55/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/appengineua.wordpress.com/55/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/appengineua.wordpress.com/55/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/appengineua.wordpress.com/55/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/appengineua.wordpress.com/55/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/appengineua.wordpress.com/55/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/appengineua.wordpress.com/55/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/appengineua.wordpress.com/55/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=appengineua.wordpress.com&amp;blog=9983379&amp;post=55&amp;subd=appengineua&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://appengineua.wordpress.com/2009/11/23/prefix-trick/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/19b55cc85f95bbd78de4dc9d798f663a?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">dchaplinsky</media:title>
		</media:content>
	</item>
		<item>
		<title>Typhoon App Engine</title>
		<link>http://appengineua.wordpress.com/2009/11/09/typhoon-app-engine/</link>
		<comments>http://appengineua.wordpress.com/2009/11/09/typhoon-app-engine/#comments</comments>
		<pubDate>Mon, 09 Nov 2009 10:02:47 +0000</pubDate>
		<dc:creator>dchaplinsky</dc:creator>
				<category><![CDATA[Общая информация]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[tricks]]></category>
		<category><![CDATA[typhoonGE]]></category>

		<guid isPermaLink="false">http://appengine.com.ua/?p=52</guid>
		<description><![CDATA[Хотите использовать Google App Engine на своем собственном сервере? Никаких проблем, для этого есть Typhoon App Engine. (за исключением того, что оно еще альфа и разработчики ни за что не ручаются). На закуску — подсказка, как запустить GAE локально под python2.6 (ну если кто сам не нашел). P.S. Спасибо Диме Харламову за наводки.<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=appengineua.wordpress.com&amp;blog=9983379&amp;post=52&amp;subd=appengineua&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>Хотите использовать Google App Engine на своем собственном сервере? Никаких проблем, для этого есть <a href="http://code.google.com/p/typhoonae/">Typhoon App Engine</a>.</p>
<p>(за исключением того, что оно еще альфа и разработчики ни за что не ручаются).</p>
<p>На закуску — <a href="http://code.google.com/p/googleappengine/issues/detail?id=1159#c7">подсказка</a>, как запустить GAE локально под python2.6 (ну если кто сам не нашел).</p>
<p>P.S. Спасибо Диме Харламову за наводки.</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/appengineua.wordpress.com/52/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/appengineua.wordpress.com/52/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/appengineua.wordpress.com/52/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/appengineua.wordpress.com/52/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/appengineua.wordpress.com/52/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/appengineua.wordpress.com/52/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/appengineua.wordpress.com/52/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/appengineua.wordpress.com/52/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/appengineua.wordpress.com/52/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/appengineua.wordpress.com/52/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/appengineua.wordpress.com/52/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/appengineua.wordpress.com/52/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/appengineua.wordpress.com/52/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/appengineua.wordpress.com/52/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=appengineua.wordpress.com&amp;blog=9983379&amp;post=52&amp;subd=appengineua&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://appengineua.wordpress.com/2009/11/09/typhoon-app-engine/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/19b55cc85f95bbd78de4dc9d798f663a?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">dchaplinsky</media:title>
		</media:content>
	</item>
		<item>
		<title>Немного javascript: измерение времени загрузки скрипта</title>
		<link>http://appengineua.wordpress.com/2009/11/03/and-finally-javascript/</link>
		<comments>http://appengineua.wordpress.com/2009/11/03/and-finally-javascript/#comments</comments>
		<pubDate>Tue, 03 Nov 2009 09:33:10 +0000</pubDate>
		<dc:creator>dchaplinsky</dc:creator>
				<category><![CDATA[Frontend]]></category>
		<category><![CDATA[ie]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[xhr]]></category>

		<guid isPermaLink="false">http://appengine.com.ua/?p=48</guid>
		<description><![CDATA[По ходу разработки проекта столкнулся с необходимостью замерять чистое время загрузки скрипта с CDN средствами javascript. Загрузка и исполнение скрипта меряется довольно легко: function loadAndExecuteScript(url, callback){ var script = document.getElementsByTagName('script')[0]; script.type = "text/javascript"; if (script.readyState){ //IE script.onreadystatechange = function(){ if (script.readyState == "loaded" &#124;&#124; script.readyState == "complete"){ script.onreadystatechange = null; callback(Number(new Date()) - t); } [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=appengineua.wordpress.com&amp;blog=9983379&amp;post=48&amp;subd=appengineua&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>По ходу разработки проекта столкнулся с необходимостью замерять чистое время загрузки скрипта с CDN средствами javascript.</p>
<p>Загрузка <strong>и исполнение</strong> скрипта меряется довольно легко:</p>
<pre style='color:#000020;background:#f6f8ff;'><span style='color:#200080;font-weight:bold;'>function</span> loadAndExecuteScript<span style='color:#308080;'>(</span>url<span style='color:#308080;'>,</span> callback<span style='color:#308080;'>)</span><span style='color:#406080;'>{</span>
      <span style='color:#200080;font-weight:bold;'>var</span> script <span style='color:#308080;'>=</span> document<span style='color:#308080;'>.</span>getElementsByTagName<span style='color:#308080;'>(</span><span style='color:#1060b6;'>'script'</span><span style='color:#308080;'>)</span><span style='color:#308080;'>[</span><span style='color:#008c00;'>0</span><span style='color:#308080;'>]</span><span style='color:#406080;'>;</span>

      script<span style='color:#308080;'>.</span>type <span style='color:#308080;'>=</span> <span style='color:#1060b6;'>"text/javascript"</span><span style='color:#406080;'>;</span>

      <span style='color:#200080;font-weight:bold;'>if</span> <span style='color:#308080;'>(</span>script<span style='color:#308080;'>.</span>readyState<span style='color:#308080;'>)</span><span style='color:#406080;'>{</span>  <span style='color:#595979;'>//IE</span>
          script<span style='color:#308080;'>.</span>onreadystatechange <span style='color:#308080;'>=</span> <span style='color:#200080;font-weight:bold;'>function</span><span style='color:#308080;'>(</span><span style='color:#308080;'>)</span><span style='color:#406080;'>{</span>
              <span style='color:#200080;font-weight:bold;'>if</span> <span style='color:#308080;'>(</span>script<span style='color:#308080;'>.</span>readyState <span style='color:#308080;'>==</span> <span style='color:#1060b6;'>"loaded"</span> <span style='color:#308080;'>||</span>
                      script<span style='color:#308080;'>.</span>readyState <span style='color:#308080;'>==</span> <span style='color:#1060b6;'>"complete"</span><span style='color:#308080;'>)</span><span style='color:#406080;'>{</span>
                  script<span style='color:#308080;'>.</span>onreadystatechange <span style='color:#308080;'>=</span> <span style='color:#0f4d75;'>null</span><span style='color:#406080;'>;</span>
                  callback<span style='color:#308080;'>(</span><span style='color:#007d45;'>Number</span><span style='color:#308080;'>(</span><span style='color:#200080;font-weight:bold;'>new</span> <span style='color:#007d45;'>Date</span><span style='color:#308080;'>(</span><span style='color:#308080;'>)</span><span style='color:#308080;'>)</span> <span style='color:#308080;'>-</span> t<span style='color:#308080;'>)</span><span style='color:#406080;'>;</span>
              <span style='color:#406080;'>}</span>
          <span style='color:#406080;'>}</span><span style='color:#406080;'>;</span>
      <span style='color:#406080;'>}</span> <span style='color:#200080;font-weight:bold;'>else</span> <span style='color:#406080;'>{</span>  <span style='color:#595979;'>//Others</span>
          script<span style='color:#308080;'>.</span>onload <span style='color:#308080;'>=</span> <span style='color:#200080;font-weight:bold;'>function</span><span style='color:#308080;'>(</span><span style='color:#308080;'>)</span><span style='color:#406080;'>{</span>
              callback<span style='color:#308080;'>(</span><span style='color:#007d45;'>Number</span><span style='color:#308080;'>(</span><span style='color:#200080;font-weight:bold;'>new</span> <span style='color:#007d45;'>Date</span><span style='color:#308080;'>(</span><span style='color:#308080;'>)</span><span style='color:#308080;'>)</span> <span style='color:#308080;'>-</span> t<span style='color:#308080;'>)</span><span style='color:#406080;'>;</span>
          <span style='color:#406080;'>}</span><span style='color:#406080;'>;</span>
      <span style='color:#406080;'>}</span>

      <span style='color:#200080;font-weight:bold;'>var</span> t <span style='color:#308080;'>=</span> <span style='color:#007d45;'>Number</span><span style='color:#308080;'>(</span><span style='color:#200080;font-weight:bold;'>new</span> <span style='color:#007d45;'>Date</span><span style='color:#308080;'>(</span><span style='color:#308080;'>)</span><span style='color:#308080;'>)</span><span style='color:#406080;'>;</span>
      script<span style='color:#308080;'>.</span>src <span style='color:#308080;'>=</span> url<span style='color:#406080;'>;</span>
  <span style='color:#406080;'>}</span>
</pre>
<p>Чтобы замерять только загрузку, приходится выкручиваться примерно вот так:</p>
<pre style='color:#000020;background:#f6f8ff;'><span style='color:#200080;font-weight:bold;'>function</span> loadScript<span style='color:#308080;'>(</span>url<span style='color:#308080;'>,</span> callback<span style='color:#308080;'>)</span> <span style='color:#406080;'>{</span>
      <span style='color:#200080;font-weight:bold;'>if</span> <span style='color:#308080;'>(</span>navigator<span style='color:#308080;'>.</span>userAgent<span style='color:#308080;'>.</span><span style='color:#200080;font-weight:bold;'>toLowerCase</span><span style='color:#308080;'>(</span><span style='color:#308080;'>)</span><span style='color:#308080;'>.</span><span style='color:#200080;font-weight:bold;'>indexOf</span><span style='color:#308080;'>(</span><span style='color:#1060b6;'>'msie'</span><span style='color:#308080;'>)</span> <span style='color:#308080;'>!==</span> <span style='color:#308080;'>-</span><span style='color:#008c00;'>1</span><span style='color:#308080;'>)</span> <span style='color:#406080;'>{</span>
          <span style='color:#200080;font-weight:bold;'>var</span> xhr <span style='color:#308080;'>=</span> window<span style='color:#308080;'>.</span><span style='color:#007d45;'>ActiveXObject</span> <span style='color:#406080;'>?</span> <span style='color:#200080;font-weight:bold;'>new</span> <span style='color:#007d45;'>ActiveXObject</span><span style='color:#308080;'>(</span><span style='color:#1060b6;'>"Microsoft.XMLHTTP"</span><span style='color:#308080;'>)</span> <span style='color:#406080;'>:</span> <span style='color:#200080;font-weight:bold;'>new</span> XMLHttpRequest<span style='color:#308080;'>(</span><span style='color:#308080;'>)</span><span style='color:#308080;'>,</span>
              time <span style='color:#308080;'>=</span> <span style='color:#0f4d75;'>false</span><span style='color:#406080;'>;</span>

          xhr<span style='color:#308080;'>.</span>onreadystatechange <span style='color:#308080;'>=</span> <span style='color:#200080;font-weight:bold;'>function</span><span style='color:#308080;'>(</span><span style='color:#308080;'>)</span> <span style='color:#406080;'>{</span>
            <span style='color:#200080;font-weight:bold;'>if</span> <span style='color:#308080;'>(</span>xhr<span style='color:#308080;'>.</span>readyState<span style='color:#308080;'>==</span><span style='color:#008c00;'>1</span> <span style='color:#308080;'>&amp;&amp;</span> !time<span style='color:#308080;'>)</span>
              time <span style='color:#308080;'>=</span> <span style='color:#007d45;'>Number</span><span style='color:#308080;'>(</span><span style='color:#200080;font-weight:bold;'>new</span> <span style='color:#007d45;'>Date</span><span style='color:#308080;'>(</span><span style='color:#308080;'>)</span><span style='color:#308080;'>)</span><span style='color:#406080;'>;</span>

            <span style='color:#200080;font-weight:bold;'>if</span> <span style='color:#308080;'>(</span>xhr<span style='color:#308080;'>.</span>readyState<span style='color:#308080;'>==</span><span style='color:#008c00;'>4</span><span style='color:#308080;'>)</span>
              callback<span style='color:#308080;'>(</span><span style='color:#007d45;'>Number</span><span style='color:#308080;'>(</span><span style='color:#200080;font-weight:bold;'>new</span> <span style='color:#007d45;'>Date</span><span style='color:#308080;'>(</span><span style='color:#308080;'>)</span><span style='color:#308080;'>)</span> <span style='color:#308080;'>-</span> time<span style='color:#308080;'>)</span><span style='color:#406080;'>;</span>
          <span style='color:#406080;'>}</span>

          xhr<span style='color:#308080;'>.</span>open<span style='color:#308080;'>(</span><span style='color:#1060b6;'>"GET"</span><span style='color:#308080;'>,</span> url<span style='color:#308080;'>,</span> <span style='color:#0f4d75;'>true</span><span style='color:#308080;'>)</span><span style='color:#406080;'>;</span>
          xhr<span style='color:#308080;'>.</span>send<span style='color:#308080;'>(</span><span style='color:#0f4d75;'>null</span><span style='color:#308080;'>)</span><span style='color:#406080;'>;</span>
      <span style='color:#406080;'>}</span>
      <span style='color:#200080;font-weight:bold;'>else</span>
      <span style='color:#406080;'>{</span>
        <span style='color:#200080;font-weight:bold;'>var</span> iframe <span style='color:#308080;'>=</span> document<span style='color:#308080;'>.</span>getElementsByTagName<span style='color:#308080;'>(</span><span style='color:#1060b6;'>'iframe'</span><span style='color:#308080;'>)</span><span style='color:#308080;'>[</span><span style='color:#008c00;'>0</span><span style='color:#308080;'>]</span><span style='color:#308080;'>,</span>
            time <span style='color:#308080;'>=</span> <span style='color:#007d45;'>Number</span><span style='color:#308080;'>(</span><span style='color:#200080;font-weight:bold;'>new</span> <span style='color:#007d45;'>Date</span><span style='color:#308080;'>(</span><span style='color:#308080;'>)</span><span style='color:#308080;'>)</span><span style='color:#406080;'>;</span>

        iframe<span style='color:#308080;'>.</span>onload <span style='color:#308080;'>=</span> <span style='color:#200080;font-weight:bold;'>function</span><span style='color:#308080;'>(</span><span style='color:#308080;'>)</span><span style='color:#406080;'>{</span>
            callback<span style='color:#308080;'>(</span><span style='color:#007d45;'>Number</span><span style='color:#308080;'>(</span><span style='color:#200080;font-weight:bold;'>new</span> <span style='color:#007d45;'>Date</span><span style='color:#308080;'>(</span><span style='color:#308080;'>)</span><span style='color:#308080;'>)</span> <span style='color:#308080;'>-</span> time<span style='color:#308080;'>)</span><span style='color:#406080;'>;</span>
        <span style='color:#406080;'>}</span><span style='color:#406080;'>;</span>

        iframe<span style='color:#308080;'>.</span>src <span style='color:#308080;'>=</span> url<span style='color:#406080;'>;</span>
      <span style='color:#406080;'>}</span>
  <span style='color:#406080;'>}</span>
</pre>
<p>Если в нормальных браузерах можно просто загрузить файл js в iframe и померять время его загрузки, то у IE, как обычно, свой путь. Увидев непривычный mime IE предложит пользователю сохранить его. Попытки загрузить JS в картинку (а также FRAME, OBJECT, и еще полдесятка тэгов) к позитивному результату также не приводит — он либо видит неожиданный mime в неожиданном месте либо не дает замерять, как в случае с BGSOUND (помните такой? :)).<br />
Я выкрутился через XHR–запрос. При попытке выполнить XHR–запрос к другому домену все браузеры обычно делают вид, как–будто ничего и не случилось (и не выполняют его), ИЕ же выдает confirmation на обращение к внешнему ресурсу. Не очень секьюрно с его стороны, но, по–крайней мере, позволяет решить мою задачу хоть как–то (без привлечения Flash через Flex).</p>
<p>Не исключено, впрочем, что проблема эта уже тысячу раз была кем–то решена, а я просто не смог найти решение. Впрочем, еще поищу :)</p>
<p>P.S.<br />
А посоветуйте хороший HTTP сниффер под Mac OS X, который умеет замерять время выполнения запросов? Хочу проверить точность результатов.</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/appengineua.wordpress.com/48/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/appengineua.wordpress.com/48/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/appengineua.wordpress.com/48/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/appengineua.wordpress.com/48/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/appengineua.wordpress.com/48/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/appengineua.wordpress.com/48/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/appengineua.wordpress.com/48/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/appengineua.wordpress.com/48/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/appengineua.wordpress.com/48/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/appengineua.wordpress.com/48/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/appengineua.wordpress.com/48/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/appengineua.wordpress.com/48/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/appengineua.wordpress.com/48/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/appengineua.wordpress.com/48/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=appengineua.wordpress.com&amp;blog=9983379&amp;post=48&amp;subd=appengineua&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://appengineua.wordpress.com/2009/11/03/and-finally-javascript/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/19b55cc85f95bbd78de4dc9d798f663a?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">dchaplinsky</media:title>
		</media:content>
	</item>
		<item>
		<title>Используем expect для установки фикстур</title>
		<link>http://appengineua.wordpress.com/2009/11/01/unexpected/</link>
		<comments>http://appengineua.wordpress.com/2009/11/01/unexpected/#comments</comments>
		<pubDate>Sat, 31 Oct 2009 23:52:41 +0000</pubDate>
		<dc:creator>dchaplinsky</dc:creator>
				<category><![CDATA[Общая информация]]></category>
		<category><![CDATA[bash]]></category>
		<category><![CDATA[datastore]]></category>
		<category><![CDATA[expect]]></category>
		<category><![CDATA[fixtures]]></category>

		<guid isPermaLink="false">http://appengine.com.ua/?p=46</guid>
		<description><![CDATA[Пару постов назад я жаловался на неудобство установки фикстур. У меня в проекте пять табличек, при перезапуске приложения GAE чистит датастор (хотя галочка отключена :-\), поэтому приходится периодически запускать пять скриптов чтобы данные залить заново. Все бы хорошо, но appcfg.py требует каждый раз вводить логин/пароль (admin:admin для локалхоста) вручную. Указать их в параметрах нельзя (по–крайней [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=appengineua.wordpress.com&amp;blog=9983379&amp;post=46&amp;subd=appengineua&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p><a href="http://appengine.com.ua/2009/10/17/fixtures/">Пару постов назад</a> я жаловался на неудобство установки фикстур. У меня в проекте пять табличек, при перезапуске приложения GAE чистит датастор (хотя галочка отключена :-\), поэтому приходится периодически запускать пять скриптов чтобы данные залить заново. Все бы хорошо, но appcfg.py требует каждый раз вводить логин/пароль (admin:admin для локалхоста) вручную. Указать их в параметрах нельзя (по–крайней мере я не нашел).</p>
<p>Помучавшись немного, решил написать <a href="http://en.wikipedia.org/wiki/Expect">expect</a>–скрипт для автоматизации этой операции (спасибо, дядя Вова!). Не знаю, как у виндовс-ребят, но под маком и никсами она есть :). Для тех, кто (как и я, до сегодняшнего вечера)  не знаком с этой чудесной программой — expect позволяет запускать различные приложения командной строки и эмулировать ввод пользователя по срабатыванию определенных триггеров (например, появления в выводе какого–нибудь слова, в нашем случае — приглашения ввести пароль). На самом деле expect умеет гораздо больше, но нам вполне хватит и этого базового функционала:</p>
<p>Вот что у меня получилось:</p>
<pre style='color:#000020;background:#f6f8ff;'>spawn appcfg.py upload_data <span style='color:#308080;'>-</span><span style='color:#074726;'>q</span> <span style='color:#308080;'>-</span><span style='color:#308080;'>-</span>config_file<span style='color:#308080;'>=</span><span style='color:#406080;'>[</span><span style='color:#200080;font-weight:bold;'>lindex</span> <span style='color:#007d45;'>$argv</span> <span style='color:#008c00;'>0</span><span style='color:#406080;'>]</span> <span style='color:#308080;'>-</span><span style='color:#308080;'>-</span><span style='color:#200080;font-weight:bold;'>filename</span><span style='color:#308080;'>=</span><span style='color:#406080;'>[</span><span style='color:#200080;font-weight:bold;'>lindex</span> <span style='color:#007d45;'>$argv</span> <span style='color:#008c00;'>1</span><span style='color:#406080;'>]</span> <span style='color:#308080;'>-</span><span style='color:#308080;'>-</span>log_file<span style='color:#308080;'>=</span><span style='color:#308080;'>/</span>d
ev<span style='color:#308080;'>/</span>null <span style='color:#308080;'>-</span><span style='color:#308080;'>-</span>kind<span style='color:#308080;'>=</span><span style='color:#406080;'>[</span><span style='color:#200080;font-weight:bold;'>lindex</span> <span style='color:#007d45;'>$argv</span> <span style='color:#008c00;'>2</span><span style='color:#406080;'>]</span> <span style='color:#308080;'>-</span><span style='color:#308080;'>-</span>url<span style='color:#308080;'>=</span>http:<span style='color:#308080;'>/</span><span style='color:#308080;'>/</span>localhost:<span style='color:#406080;'>[</span><span style='color:#200080;font-weight:bold;'>lindex</span> <span style='color:#007d45;'>$argv</span> <span style='color:#008c00;'>3</span><span style='color:#406080;'>]</span><span style='color:#308080;'>/</span>remote_api .<span style='color:#308080;'>/</span>

expect <span style='color:#406080;'>{</span>
    Password <span style='color:#406080;'>{</span> <span style='color:#200080;font-weight:bold;'>send</span> admin<span style='color:#0000cc;'>\r</span><span style='color:#308080;'>;</span> exp_continue <span style='color:#406080;'>}</span>
    Email <span style='color:#406080;'>{</span> <span style='color:#200080;font-weight:bold;'>send</span> admin<span style='color:#0000cc;'>\r</span><span style='color:#308080;'>;</span> exp_continue <span style='color:#406080;'>}</span>
<span style='color:#406080;'>}</span>
</pre>
<p>Вызывается это счастье следущим образом:</p>
<pre style='color:#000020;background:#f6f8ff;'>expect .<span style='color:#40015a;'>/test</span><span style='color:#200080;font-weight:bold;'>.</span>exp cdn_loader<span style='color:#200080;font-weight:bold;'>.</span>py cdn_data<span style='color:#200080;font-weight:bold;'>.</span>csv CDN <span style='color:#008c00;'>8081</span>
</pre>
<p>Где параметры означают:</p>
<ol>
<li>скрипт–загрузчик</li>
<li>CSV с данными</li>
<li>kind датастора</li>
<li>Порт вашего приложения</li>
</ol>
<p>Соответственно, можно сделать один sh скрипт, который будет загружать все данные во все таблицы.</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/appengineua.wordpress.com/46/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/appengineua.wordpress.com/46/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/appengineua.wordpress.com/46/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/appengineua.wordpress.com/46/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/appengineua.wordpress.com/46/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/appengineua.wordpress.com/46/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/appengineua.wordpress.com/46/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/appengineua.wordpress.com/46/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/appengineua.wordpress.com/46/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/appengineua.wordpress.com/46/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/appengineua.wordpress.com/46/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/appengineua.wordpress.com/46/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/appengineua.wordpress.com/46/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/appengineua.wordpress.com/46/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=appengineua.wordpress.com&amp;blog=9983379&amp;post=46&amp;subd=appengineua&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://appengineua.wordpress.com/2009/11/01/unexpected/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/19b55cc85f95bbd78de4dc9d798f663a?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">dchaplinsky</media:title>
		</media:content>
	</item>
		<item>
		<title>Новый адрес</title>
		<link>http://appengineua.wordpress.com/2009/10/28/new-larrys-suit/</link>
		<comments>http://appengineua.wordpress.com/2009/10/28/new-larrys-suit/#comments</comments>
		<pubDate>Wed, 28 Oct 2009 14:39:25 +0000</pubDate>
		<dc:creator>dchaplinsky</dc:creator>
				<category><![CDATA[Общая информация]]></category>

		<guid isPermaLink="false">http://appengine.com.ua/?p=43</guid>
		<description><![CDATA[Этот сайт теперь доступен по человеческому адресу appengine.com.ua. Обновите ваши закладки :) Вордпресс, оказывается, берет целых 10 баксов за привязку домена, зато умеет включать для него Google MX.<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=appengineua.wordpress.com&amp;blog=9983379&amp;post=43&amp;subd=appengineua&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>Этот сайт теперь доступен по человеческому адресу <a href="http://appengine.com.ua">appengine.com.ua</a>. Обновите ваши закладки :)</p>
<p>Вордпресс, оказывается, берет целых 10 баксов за привязку домена, зато умеет включать для него Google MX.</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/appengineua.wordpress.com/43/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/appengineua.wordpress.com/43/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/appengineua.wordpress.com/43/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/appengineua.wordpress.com/43/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/appengineua.wordpress.com/43/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/appengineua.wordpress.com/43/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/appengineua.wordpress.com/43/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/appengineua.wordpress.com/43/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/appengineua.wordpress.com/43/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/appengineua.wordpress.com/43/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/appengineua.wordpress.com/43/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/appengineua.wordpress.com/43/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/appengineua.wordpress.com/43/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/appengineua.wordpress.com/43/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=appengineua.wordpress.com&amp;blog=9983379&amp;post=43&amp;subd=appengineua&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://appengineua.wordpress.com/2009/10/28/new-larrys-suit/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/19b55cc85f95bbd78de4dc9d798f663a?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">dchaplinsky</media:title>
		</media:content>
	</item>
		<item>
		<title>Пара ссылок</title>
		<link>http://appengineua.wordpress.com/2009/10/26/bargain-bin/</link>
		<comments>http://appengineua.wordpress.com/2009/10/26/bargain-bin/#comments</comments>
		<pubDate>Mon, 26 Oct 2009 09:06:31 +0000</pubDate>
		<dc:creator>dchaplinsky</dc:creator>
				<category><![CDATA[Общая информация]]></category>
		<category><![CDATA[книги]]></category>
		<category><![CDATA[ссылки]]></category>
		<category><![CDATA[статьи]]></category>

		<guid isPermaLink="false">http://appengineua.wordpress.com/?p=39</guid>
		<description><![CDATA[Здесь немного общей информации. Здесь хулят книгу по GAE от Apress O’Reilly Media. Печально, но похоже все так и есть.<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=appengineua.wordpress.com&amp;blog=9983379&amp;post=39&amp;subd=appengineua&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.insight-it.ru/programming/django-v-gostyakh-u-google/">Здесь</a> немного общей информации.</p>
<p><a href="http://xenru.livejournal.com/163860.html">Здесь</a> хулят книгу по GAE от <span style="text-decoration:line-through;">Apress</span> O’Reilly Media. Печально, но похоже все так и есть.</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/appengineua.wordpress.com/39/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/appengineua.wordpress.com/39/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/appengineua.wordpress.com/39/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/appengineua.wordpress.com/39/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/appengineua.wordpress.com/39/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/appengineua.wordpress.com/39/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/appengineua.wordpress.com/39/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/appengineua.wordpress.com/39/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/appengineua.wordpress.com/39/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/appengineua.wordpress.com/39/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/appengineua.wordpress.com/39/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/appengineua.wordpress.com/39/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/appengineua.wordpress.com/39/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/appengineua.wordpress.com/39/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=appengineua.wordpress.com&amp;blog=9983379&amp;post=39&amp;subd=appengineua&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://appengineua.wordpress.com/2009/10/26/bargain-bin/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/19b55cc85f95bbd78de4dc9d798f663a?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">dchaplinsky</media:title>
		</media:content>
	</item>
	</channel>
</rss>
