<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/atom10full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><feed xmlns="http://www.w3.org/2005/Atom" xmlns:openSearch="http://a9.com/-/spec/opensearch/1.1/" xmlns:georss="http://www.georss.org/georss" xmlns:gd="http://schemas.google.com/g/2005" xmlns:thr="http://purl.org/syndication/thread/1.0" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" gd:etag="W/&quot;Dk8ER3s8eCp7ImA9WhVUE0g.&quot;"><id>tag:blogger.com,1999:blog-2025136836330523605</id><updated>2012-05-18T18:26:46.570+03:00</updated><category term="logging" /><category term="processing" /><category term="control" /><category term="protocol" /><category term="free" /><category term="development" /><category term="production" /><category term="stylesheet" /><category term="command prompt" /><category term="hash" /><category term="conversion" /><category term="info" /><category term="api" /><category term="service" /><category term="threading" /><category term="win32" /><category term="cource" /><category term="practice" /><category term="aliases" /><category term="disco" /><category term="sha224" /><category term="rss" /><category term="web.py" /><category term="video" /><category term="nosql" /><category term="clientlogin" /><category term="training" /><category term="opera" /><category term="protection" /><category term="sha512" /><category term="facebook" /><category term="scheme" /><category term="key-value" /><category term="visualization" /><category term="tornado" /><category term="authentication" /><category term="friendfeed" /><category term="core" /><category term="intro" /><category term="example" /><category term="guid" /><category term="fetch" /><category term="sha384" /><category term="conveyor" /><category term="lambda" /><category term="ideas" /><category term="camp" /><category term="artificial" /><category term="online" /><category term="rest" /><category term="introspection" /><category term="interview" /><category term="text" /><category term="flickr" /><category term="design" /><category term="network" /><category term="ubuntu" /><category term="datetime" /><category term="tree" /><category term="json" /><category term="google" /><category term="sha1" /><category term="feeds" /><category term="technology" /><category term="cluster" /><category term="decorator" /><category term="secure" /><category term="ticket" /><category term="template" /><category term="application" /><category term="sync" /><category term="it" /><category term="Steve Jobs" /><category term="portable" /><category term="flow" /><category term="nokia" /><category term="description" /><category term="packet" /><category term="course" /><category term="compare" /><category term="stanford" /><category term="code" /><category term="feedparser" /><category term="async" /><category term="learning" /><category term="pyflowctrl" /><category term="comments" /><category term="unique" /><category term="kvlite" /><category term="walker" /><category term="lifehack" /><category term="processor" /><category term="reduce" /><category term="sqlite" /><category term="indexing" /><category term="post" /><category term="thread" /><category term="gae" /><category term="queue" /><category term="jquery" /><category term="identity" /><category term="datatype" /><category term="task" /><category term="kamaelia" /><category term="server" /><category term="md5" /><category term="install" /><category term="erlang" /><category term="html5" /><category term="web" /><category term="system tray" /><category term="profiler" /><category term="mapreduce" /><category term="hadoop" /><category term="library" /><category term="presentation" /><category term="firefox" /><category term="test" /><category term="pool" /><category term="hint" /><category term="stdin" /><category term="css" /><category term="intelligence" /><category term="performance" /><category term="review" /><category term="get" /><category term="miltuthread" /><category term="cpu" /><category term="sha256" /><category term="generator" /><category term="notes" /><category term="overview" /><category term="xml" /><category term="business" /><category term="advice" /><category term="mysql" /><category term="logic" /><category term="seminar" /><category term="datastore" /><category term="css3" /><category term="machine" /><category term="cloud" /><category term="school" /><category term="testlab" /><category term="game" /><category term="data center" /><category term="filter" /><category term="chrome os" /><category term="people" /><category term="html" /><category term="reference" /><category term="stdout" /><category term="atom" /><category term="architecture" /><category term="data munging" /><category term="widget" /><category term="request" /><category term="computing" /><category term="disqus" /><category term="url" /><category term="media" /><category term="extract" /><category term="javascript" /><category term="complex" /><category term="apple" /><category term="fast" /><category term="map" /><category term="architechure" /><category term="skype" /><category term="social" /><category term="benchmark" /><category term="directory" /><category term="youtube" /><category term="conference" /><category term="curl" /><category term="http" /><category term="graphviz" /><category term="start-up" /><category term="concurrent" /><category term="daemon" /><category term="console" /><category term="download" /><category term="find" /><category term="dynamo" /><category term="developers" /><category term="approach" /><category term="python" /><category term="analysis" /><category term="amazon" /><category term="internet" /><category term="parallel" /><category term="windows" /><category term="open" /><category term="ukraine" /><category term="stderr" /><category term="timestamp" /><category term="file" /><category term="authorization" /><category term="database" /><category term="science" /><category term="linux" /><category term="debug" /><category term="key" /><category term="feed" /><category term="research" /><category term="cygwin" /><category term="process" /><category term="programming" /><category term="simple" /><category term="yandex" /><category term="font" /><category term="mongodb" /><category term="book" /><category term="blog" /><category term="kvlite2" /><category term="time" /><category term="kiev" /><category term="blogger" /><category term="dictionary" /><category term="search" /><category term="structure" /><category term="mozilla" /><category term="data" /><category term="metadata" /><category term="reader" /><category term="distribution" /><title>Development for fun</title><subtitle type="html">Разработка как хобби</subtitle><link rel="http://schemas.google.com/g/2005#feed" type="application/atom+xml" href="http://devel.ownport.net/feeds/posts/default" /><link rel="alternate" type="text/html" href="http://devel.ownport.net/" /><link rel="next" type="application/atom+xml" href="http://www.blogger.com/feeds/2025136836330523605/posts/default?start-index=26&amp;max-results=25&amp;redirect=false&amp;v=2" /><author><name>d.rey</name><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><generator version="7.00" uri="http://www.blogger.com">Blogger</generator><openSearch:totalResults>133</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/atom+xml" href="http://feeds.feedburner.com/develforfun" /><feedburner:info uri="develforfun" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><entry gd:etag="W/&quot;CkUGRn8yfCp7ImA9WhVVFE8.&quot;"><id>tag:blogger.com,1999:blog-2025136836330523605.post-3817440544737415836</id><published>2012-05-07T22:50:00.000+03:00</published><updated>2012-05-07T22:50:27.194+03:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-05-07T22:50:27.194+03:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="development" /><category scheme="http://www.blogger.com/atom/ns#" term="lifehack" /><title>Разработка и ремонт в квартире</title><content type="html">Разработку можно сравнить с ремонтом в квартире. Изначально планируется одно. Когда работа подходит к завершению, понимаешь, что еще в нескольких местах стоит переделать, а потом и еще в нескольких... А потом понимаешь, что если бы ты начал делать ремонт сейчас, то делал бы все совершенно по другому. Только вопрос в том, что не каждый может набраться смелости и переделать ремонт с нуля. А зачастую, получается так, что уже нет ни времени, ни возможностей.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2025136836330523605-3817440544737415836?l=devel.ownport.net' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/develforfun/~4/Le1bUl9EEcY" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://devel.ownport.net/feeds/3817440544737415836/comments/default" title="Комментарии к сообщению" /><link rel="replies" type="text/html" href="http://devel.ownport.net/2012/05/blog-post.html#comment-form" title="Комментарии: 0" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/2025136836330523605/posts/default/3817440544737415836?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/2025136836330523605/posts/default/3817440544737415836?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/develforfun/~3/Le1bUl9EEcY/blog-post.html" title="Разработка и ремонт в квартире" /><author><name>d.rey</name><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>0</thr:total><feedburner:origLink>http://devel.ownport.net/2012/05/blog-post.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CEcGQX86fSp7ImA9WhVVEU0.&quot;"><id>tag:blogger.com,1999:blog-2025136836330523605.post-857118461505771287</id><published>2012-05-04T06:11:00.003+03:00</published><updated>2012-05-04T06:27:00.115+03:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-05-04T06:27:00.115+03:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="start-up" /><category scheme="http://www.blogger.com/atom/ns#" term="ideas" /><category scheme="http://www.blogger.com/atom/ns#" term="developers" /><category scheme="http://www.blogger.com/atom/ns#" term="business" /><category scheme="http://www.blogger.com/atom/ns#" term="book" /><title>Книга Business of Software</title><content type="html">&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/-4-iGxtV5jhE/T6NH6_Nu1GI/AAAAAAAAAgE/3GIE0YTK4X4/s1600/business-of-software.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://3.bp.blogspot.com/-4-iGxtV5jhE/T6NH6_Nu1GI/AAAAAAAAAgE/3GIE0YTK4X4/s1600/business-of-software.png" /&gt;&lt;/a&gt;&lt;/div&gt;Благодаря майским праздникам удалось найти немного времени и прочесть книгу &lt;a href="http://www.amazon.com/Business-Software-Experts-Voice-ebook/dp/B001D7JO0Q/"&gt;Business of Software&lt;/a&gt;. Автор книги - разработчик, основатель &lt;a href="http://www.sourcegear.com/"&gt;SourceGear&lt;/a&gt;, &lt;a href="http://www.ericsink.com/"&gt;блоггер&lt;/a&gt;. Книга написана на основании наиболее популярных эссе из блога. Читается легко, интерестно, живо и с юмором. Расскрываются и обсуждаются вопросы, которые встречает каждый разработчик, желающий начать свое дело: выбор идеи, реализация, финансы, найм новых сотрудников, маркетинг, построение работы внутри команды. В книге много примеров. Практически к каждой обсуждаемой теме приводятся параллели из других областей.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2025136836330523605-857118461505771287?l=devel.ownport.net' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/develforfun/~4/JXqQuJda0LU" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://devel.ownport.net/feeds/857118461505771287/comments/default" title="Комментарии к сообщению" /><link rel="replies" type="text/html" href="http://devel.ownport.net/2012/05/business-of-software.html#comment-form" title="Комментарии: 0" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/2025136836330523605/posts/default/857118461505771287?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/2025136836330523605/posts/default/857118461505771287?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/develforfun/~3/JXqQuJda0LU/business-of-software.html" title="Книга Business of Software" /><author><name>d.rey</name><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://3.bp.blogspot.com/-4-iGxtV5jhE/T6NH6_Nu1GI/AAAAAAAAAgE/3GIE0YTK4X4/s72-c/business-of-software.png" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://devel.ownport.net/2012/05/business-of-software.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DU8ARn0_eCp7ImA9WhVVEEw.&quot;"><id>tag:blogger.com,1999:blog-2025136836330523605.post-1781928393881886082</id><published>2012-05-03T06:57:00.000+03:00</published><updated>2012-05-03T07:04:07.340+03:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-05-03T07:04:07.340+03:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="install" /><category scheme="http://www.blogger.com/atom/ns#" term="network" /><category scheme="http://www.blogger.com/atom/ns#" term="linux" /><category scheme="http://www.blogger.com/atom/ns#" term="ubuntu" /><category scheme="http://www.blogger.com/atom/ns#" term="console" /><title>Установка Ubuntu 12.04: жесткий диск + сетевая консоль</title><content type="html">&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/-qPZSAIcSdJI/T6GhuptB7vI/AAAAAAAAAf0/hbvvIiy2df8/s1600/ubuntu-12.04.png" imageanchor="1" style="clear:left; float:left;margin-right:1em; margin-bottom:1em"&gt;&lt;img border="0" height="150" width="150" src="http://3.bp.blogspot.com/-qPZSAIcSdJI/T6GhuptB7vI/AAAAAAAAAf0/hbvvIiy2df8/s320/ubuntu-12.04.png" /&gt;&lt;/a&gt;&lt;/div&gt;Прошел почти год с публикации поста про &lt;a href="http://devel.ownport.net/2011/05/ubuntu-1104.html"&gt;установку Ubuntu с сетевой консоли&lt;/a&gt;. Несколько раз &lt;a href="http://code.google.com/p/sources-ownport/downloads/list"&gt;инсталляционные образы&lt;/a&gt; выручали, когда нужно было установить систему без монитора и клавиатуры. Но несколько дней назад понадобилось установить Ubuntu на компьютер, который планировалось использовать как небольшой сервер. Монитора и клавиатуры под рукой не оказалось, да и загрузка с USB Drive в BIOS выключена. Безвыходных ситуаций не бывает, поэтому и решение нашлось - установка Ubuntu 12.04 с жесткого диска.&lt;br /&gt;
&lt;a name='more'&gt;&lt;/a&gt;&lt;br /&gt;
Основная задача: обеспечить возможность загрузки с жесткого диска, дальнейшая установка должна быть выполнена через сетевую консоль.&lt;br /&gt;
&lt;br /&gt;
Для этого необходимо:&lt;br /&gt;
- &lt;a href="https://help.ubuntu.com/community/Installation/MinimalCD"&gt;минимальный образ Ubuntu 12.04&lt;/a&gt; &lt;br /&gt;
- внешний карман для жесткого 3,5” диска. В моем случае использовался &lt;a href="http://www.welland.com.tw/html/enclosure/700.html"&gt;SunBright&lt;/a&gt;, поддерживающий как IDE так и SATA интерфейсы&lt;br /&gt;
- компьютер или лептоп с установленым Linux. В примерах ниже используется Ubuntu 12.04 Desktop&lt;br /&gt;
- &lt;a href="https://www.virtualbox.org/"&gt;VirtualBox&lt;/a&gt;, опционально, необходим для проверки работы и тестирования.&lt;br /&gt;
&lt;br /&gt;
Из компьютера, на который планируется установка Ubuntu, необходимо извлечь жесткий диск и подключить через внешний карман c USB интерфейсом к компьютеру или лептопу с предустановленной Ubuntu. Если на жестком диске есть важные данные, лучше сделать их резервную копию. С помощью fdisk иди gparted http://gparted.sourceforge.net/ делается разбивка файловой системы. Для упрощения можно выделить два раздела: один для swap, другой для root (/). Для root выбираем ext4 файловую систему. Важно не забыть пометить root раздел как загрузочный (Boot).&lt;br /&gt;
&lt;br /&gt;
Далее необходимо установить grub на новый раздел (/media/newroot -&amp;gt; /dev/sdb2): &lt;pre&gt;# sudo grub-install --root-directory /media/newroot /dev/sdb&lt;/pre&gt;где /dev/sdb - диск на который будет установлен Grub. Необходимо быть очень аккуратным при выполнении команд, что бы не перезаписать существующие разделы на рабочем компьютере&lt;br /&gt;
&lt;br /&gt;
Как результат, после выполнения команды на диске будет создана директория /boot/grub с множеством файлов, необходимых для работы grub. Для нас будет важен только файл /boot/grub/grub.cfg. Перед тем, как вносить изменения в конфигурационый файл, необходимо скопировать два файла linux и initrd.gz из образа для Ubuntu 12.04 (ubuntu-12.04-mini-i386.iso) в директорию /boot/newinstall. После этого пераписываем файл grub.cfg на /dev/sdb2, файлом: &lt;pre&gt;set root=(hd0,2) # значение (hd0,2) необходимо переназначить в 
                 # зависимости от актуальной конфигурации 
linux /boot/newinstall/linux \
      locale=en_US  \
      console-setup/ask_detect=false \
      console-setup/layoutcode=ru \
      anna/choose_modules=network-console \
      network-console/password=r00tme \
      network-console/password-again=r00tme \
      debconf/priority=critical --
initrd /boot/newinstall/initrd.gz
boot &lt;/pre&gt;По сути, это все. Можно подключать диск компьютеру и выполнять загрузку. Если все хорошо, то буквально через пару минут вы сможете подключиться к новому серверу через ssh (login: installer, password: r00tme): &lt;pre&gt;# ssh installer@&amp;lt;server_ip_address&amp;gt; &lt;/pre&gt;и продолжить инсталяцию. &lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Опционально&lt;/b&gt;. Перед установка жесткого диска в сервер, новую конфигурацию можно проверить с помощью VirtualBox. Дело в том, что VirtualBox позволяет работать с реальными разделами на жестких дисках через vmdk файлы. Для создания такого файла необходимо выполнить следующую команду: &lt;pre&gt;# sudo vboxmanage internalcommands createrawvmdk -filename usb-hdd320.vmdk -rawdisk /dev/sdb 

RAW host disk access VMDK file usb-hdd320.vmdk created successfully. &lt;/pre&gt;Далее необходимо создать виртуальную машину для работы с жестким диском через vmdk файл &lt;pre&gt;sudo vboxmanage createvm --name minilab --ostype Ubuntu --register
sudo vboxmanage modifyvm minilab --memory 512
sudo vboxmanage storagectl minilab --name "IDE Controller" --add ide
sudo vboxmanage storageattach minilab --storagectl "IDE Controller" --port=0 --device=0 --type hdd --medium /media/data/vm/usb-hdd320.vmdk &lt;/pre&gt;Запускается виртуальная машина minilab с помощью: &lt;pre&gt;sudo vboxmanage startvm minilab&lt;/pre&gt;Если все хорошо, то через пару минут в окне виртульный машины вы увидите приглашение продолжить установку через сетевую консоль: ssh installer@&amp;lt;vm_ip_address&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Ссылки&lt;/b&gt;&lt;br /&gt;
&lt;a href="http://www.bloof.de/virtualBox_headless"&gt;VirtualBox headless setup&lt;/a&gt;&lt;br /&gt;
&lt;a href="http://habrahabr.ru/post/104029/"&gt;Автоматическая преднастроенная установка Ubuntu: isolinux и preseed&lt;/a&gt;&lt;br /&gt;
&lt;a href="https://help.ubuntu.com/12.04/installation-guide/example-preseed.txt"&gt;Preseed example, Ubuntu 12.04, installation guideline&lt;/a&gt;&lt;br /&gt;
&lt;a href="http://releases.ubuntu.com/12.04/"&gt;Ubuntu 12.04 releases&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2025136836330523605-1781928393881886082?l=devel.ownport.net' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/develforfun/~4/NkFHVOib0AY" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://devel.ownport.net/feeds/1781928393881886082/comments/default" title="Комментарии к сообщению" /><link rel="replies" type="text/html" href="http://devel.ownport.net/2012/05/ubuntu-1204.html#comment-form" title="Комментарии: 0" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/2025136836330523605/posts/default/1781928393881886082?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/2025136836330523605/posts/default/1781928393881886082?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/develforfun/~3/NkFHVOib0AY/ubuntu-1204.html" title="Установка Ubuntu 12.04: жесткий диск + сетевая консоль" /><author><name>d.rey</name><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://3.bp.blogspot.com/-qPZSAIcSdJI/T6GhuptB7vI/AAAAAAAAAf0/hbvvIiy2df8/s72-c/ubuntu-12.04.png" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://devel.ownport.net/2012/05/ubuntu-1204.html</feedburner:origLink></entry><entry gd:etag="W/&quot;A08ARHg4fyp7ImA9WhVWFEw.&quot;"><id>tag:blogger.com,1999:blog-2025136836330523605.post-6740888104015012292</id><published>2012-04-26T07:49:00.000+03:00</published><updated>2012-04-26T08:57:25.637+03:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-04-26T08:57:25.637+03:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="blog" /><title>Небольшой рубеж</title><content type="html">&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://1.bp.blogspot.com/-pk5rYdaE4Ds/T5jTI8aXMTI/AAAAAAAAAfg/6qPPCjQJzB4/s1600/%D0%BD%D0%B5%D0%B1%D0%BE%D0%BB%D1%8C%D1%88%D0%BE%D0%B9+%D1%80%D1%83%D0%B1%D0%B5%D0%B6.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://1.bp.blogspot.com/-pk5rYdaE4Ds/T5jTI8aXMTI/AAAAAAAAAfg/6qPPCjQJzB4/s1600/%D0%BD%D0%B5%D0%B1%D0%BE%D0%BB%D1%8C%D1%88%D0%BE%D0%B9+%D1%80%D1%83%D0%B1%D0%B5%D0%B6.png" /&gt;&lt;/a&gt;&lt;/div&gt;
Это конечно не какое-то выдающееся событие, но все равно приятно&lt;br /&gt;
&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2025136836330523605-6740888104015012292?l=devel.ownport.net' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/develforfun/~4/UutXshJQmjw" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://devel.ownport.net/feeds/6740888104015012292/comments/default" title="Комментарии к сообщению" /><link rel="replies" type="text/html" href="http://devel.ownport.net/2012/04/blog-post.html#comment-form" title="Комментарии: 0" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/2025136836330523605/posts/default/6740888104015012292?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/2025136836330523605/posts/default/6740888104015012292?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/develforfun/~3/UutXshJQmjw/blog-post.html" title="Небольшой рубеж" /><author><name>d.rey</name><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://1.bp.blogspot.com/-pk5rYdaE4Ds/T5jTI8aXMTI/AAAAAAAAAfg/6qPPCjQJzB4/s72-c/%D0%BD%D0%B5%D0%B1%D0%BE%D0%BB%D1%8C%D1%88%D0%BE%D0%B9+%D1%80%D1%83%D0%B1%D0%B5%D0%B6.png" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://devel.ownport.net/2012/04/blog-post.html</feedburner:origLink></entry><entry gd:etag="W/&quot;A0UCRHYzcSp7ImA9WhVXF08.&quot;"><id>tag:blogger.com,1999:blog-2025136836330523605.post-1363702241160019159</id><published>2012-04-18T09:07:00.000+03:00</published><updated>2012-04-18T09:07:45.889+03:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-04-18T09:07:45.889+03:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="kvlite2" /><category scheme="http://www.blogger.com/atom/ns#" term="fetch" /><category scheme="http://www.blogger.com/atom/ns#" term="python" /><category scheme="http://www.blogger.com/atom/ns#" term="feedparser" /><category scheme="http://www.blogger.com/atom/ns#" term="rss" /><title>Изменения в rssfetch</title><content type="html">&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/-snKr7NfoYvc/S-Bs2snY0uI/AAAAAAAAAJA/ITWeo5zc5DE/s1600/100px-Feed-icon.svg.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://2.bp.blogspot.com/-snKr7NfoYvc/S-Bs2snY0uI/AAAAAAAAAJA/ITWeo5zc5DE/s1600/100px-Feed-icon.svg.png" /&gt;&lt;/a&gt;&lt;/div&gt;Опубликовал новую версию rssfetch &lt;a href="http://code.google.com/p/sources-ownport/source/browse/rssfetch"&gt;http://code.google.com/p/sources-ownport/source/browse/rssfetch&lt;/a&gt; - загрузчик RSS лент с использованием Universal Feed Parser и KVLite2, используемый для периодической проверки наличия новых постов для выбранных RSS лент и хранение их в базе данных для последующей обработки. &lt;br /&gt;
&lt;a name='more'&gt;&lt;/a&gt;&lt;br /&gt;
Изменения:&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;rssfetch перешел на хранение RSS данных в &lt;a href="http://devel.ownport.net/2012/03/pysimplefeed-rss.html"&gt;PySimpleFeed формате&lt;/a&gt;. Это позволило значительно упростить и унифицировать структуру данных. Выигрыш от использования PySimpleFeed - экономия порядка 40% дисковой емкости. Для миграции старых данных с использованием нового формата необходимо воспользоваться скриптом migr.py.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Важно&lt;/b&gt;: Перед использование скрипта migr.py необходимо выполнять резераное хранение данных.&lt;br /&gt;
&lt;pre&gt;# python migr.py --migrate_to_simplefeed&lt;/pre&gt;&lt;/li&gt;
&lt;li&gt;используется единый формат представления даты и времени для полей  entry.published, entry.updated, entry.edited. Для обновления существующих данных &lt;pre&gt;# python migr.py --unify_datetime&lt;/pre&gt;&lt;/li&gt;
&lt;li&gt;при добавлении новых постов в базу данных  добавляются поля entry.source.sha1 и entry.source.href, содержащие SHA1 хеш и ссылку на RSS ленту. Для добавления этих полей для существующих данных:&lt;br /&gt;
&lt;pre&gt;# python migr.py --update_source&lt;/pre&gt;&lt;/li&gt;
&lt;li&gt;для каждой ленты feed добавлены новые поля ‘last_updated’ и ‘posts_per_requrest’. Значение этих полей использутся для вычисления времени, когда необходимо выполнять запрос на наличие новых постов для каждой ленты.&lt;/li&gt;
&lt;li&gt;исправлена проблема с хранением и передачей ETag&lt;/li&gt;
&lt;li&gt;добавлена новая функциональность - вывод дополнительной информации о RSS лентах: порядковый номер ленты, SHA1 хеш от сссылки на ленту, диаграмма появления новых постов от времени, дата и время последней модификации по информации от сервера, дата и время последнего опроса rssfetch, значение ETag, ссылка на ленту, число постов в ответе сервера&lt;/li&gt;
&lt;li&gt;PySimpleFeed удаляет поля со значением None&lt;/li&gt;
&lt;li&gt;добавлена оптимизация запросов к серверам на наличие новых данных. При первом запуске rssfetch.py -u, за сутки, опрашиваются все ленты. Установлено органичение на опрос одной и той же ленты не чаще чем раз за интервал, установленый в параметре settings.TIME_INTERVAL. На основе истории предыдущих запросов прнимается решение о выполнении запроса к серверу, если за интервал времени от последнего опроса до текущего времени было опубликовано постов больше половины от общего количества постов, возвращаемых за один ответ от сервера. Для обновления матрицы распределения даты и времени постов необходимо выполнить команду&lt;pre&gt;# python rssfetch.py --update_factor&lt;/pre&gt;&lt;/li&gt;
&lt;li&gt;в получаемых данных для некоторых лент поля entry.edited, entry.published, entry.updated не заполнены, это приводит к некорректному формированию матрицы распределения постов. Для того, чтобы минимизировать отклоннения, для постов которые не содержат данных полей rssfetch формирует поле entry.updated с указанием даты и времени опроса ленты&lt;/li&gt;
&lt;li&gt;добавлена возможность выполнения оптимизации и изменения структуры полей для существующих постов. Зачастую при добавлении новых лент появляются и новые поля, которые ранее не были описаны в PySimpleFeed. Большинство из этих новых полей переносятся в “черный” список, т.к. не содежат полезной информации. Запуск &lt;pre&gt;# python rssfetch.py --optimize_fields&lt;/pre&gt;позволяет привести посты всех лент к единому формату в случае внесения изменений в  PySimpleFeed формате или если поля внесены в  “черный” список&lt;br /&gt;
&lt;/li&gt;
&lt;li&gt;добавлена возможность выводить информацию по всем полям хранимых в базе данных, их частоте использования, а также если поле не внесено в список FIXED_FIELD_LIST, то промаркировать его со статусом ‘new’. Пример вывода для тестовой базы:&lt;pre&gt;{u'entry.authors': {'count': 2070},
u'entry.comments': {'count': 1307},
u'entry.content.html': {'count': 1818},
u'entry.content.rights': {'count': 118},
u'entry.content.subtitle': {'count': 251},
u'entry.content.text': {'count': 168},
u'entry.content.xml': {'count': 2},
u'entry.edited': {'count': 125},
u'entry.language': {'count': 134},
u'entry.links': {'count': 3196},
u'entry.media.urls': {'count': 847},
u'entry.published': {'count': 4117},
u'entry.publisher': {'count': 118},
u'entry.source.href': {'count': 3196},
u'entry.source.sha1': {'count': 4305},
u'entry.summary': {'count': 4286},
u'entry.tags.scheme': {'count': 1286},
u'entry.tags.term': {'count': 3340},
u'entry.text': {'count': 47},
u'entry.title': {'count': 4279},
u'entry.updated': {'count': 917}}
Total feed entries: 4305&lt;/pre&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2025136836330523605-1363702241160019159?l=devel.ownport.net' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/develforfun/~4/jP5vaRktI6A" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://devel.ownport.net/feeds/1363702241160019159/comments/default" title="Комментарии к сообщению" /><link rel="replies" type="text/html" href="http://devel.ownport.net/2012/04/rssfetch.html#comment-form" title="Комментарии: 0" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/2025136836330523605/posts/default/1363702241160019159?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/2025136836330523605/posts/default/1363702241160019159?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/develforfun/~3/jP5vaRktI6A/rssfetch.html" title="Изменения в rssfetch" /><author><name>d.rey</name><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://2.bp.blogspot.com/-snKr7NfoYvc/S-Bs2snY0uI/AAAAAAAAAJA/ITWeo5zc5DE/s72-c/100px-Feed-icon.svg.png" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://devel.ownport.net/2012/04/rssfetch.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CkUFRXY9eip7ImA9WhVQEUo.&quot;"><id>tag:blogger.com,1999:blog-2025136836330523605.post-2823727670787880894</id><published>2012-03-31T08:03:00.000+03:00</published><updated>2012-03-31T08:03:34.862+03:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-03-31T08:03:34.862+03:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="python" /><category scheme="http://www.blogger.com/atom/ns#" term="simple" /><category scheme="http://www.blogger.com/atom/ns#" term="feed" /><category scheme="http://www.blogger.com/atom/ns#" term="rss" /><title>PySimpleFeed: компактное представление структуры RSS новостей</title><content type="html">&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/-snKr7NfoYvc/S-Bs2snY0uI/AAAAAAAAAJA/ITWeo5zc5DE/s1600/100px-Feed-icon.svg.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://2.bp.blogspot.com/-snKr7NfoYvc/S-Bs2snY0uI/AAAAAAAAAJA/ITWeo5zc5DE/s1600/100px-Feed-icon.svg.png" /&gt;&lt;/a&gt;&lt;/div&gt;В &lt;a href="http://devel.ownport.net/2012/03/blog-post.html"&gt;прошлом посте&lt;/a&gt; приводился  пример вывода агрегированной структуры rss постов для нескольких десятков тысяч постов. Даже на таком сравнительно небольшом наборе данных становится понятно, насколько может быть разнообразна и избыточна структура RSS/Atom данных. Небольшая библиотека &lt;a href="http://code.google.com/p/sources-ownport/source/browse/rssfetch/pysimplefeed.py"&gt;PySimpleFeed&lt;/a&gt; позволяет привести структуру данных, полученных с помощью &lt;a href="http://code.google.com/p/feedparser/"&gt;feedparser.feed()&lt;/a&gt; к плоскому виду, убрать избыточноть, сократить число необходимых для анализа полей с нескольких сотен до десятков. Пример агрегированной структуры из прошлого поста с использование PySimpleFeed выглядит следующим образом: &lt;br /&gt;
&lt;a name='more'&gt;&lt;/a&gt;&lt;pre&gt;{u'entry.authors': 18734,
 u'entry.comments': 7556,
 u'entry.content.html': 7647,
 u'entry.content.rights': 129,
 u'entry.content.subtitle': 256,
 u'entry.content.text': 166,
 u'entry.content.xml': 2,
 u'entry.edited': 239,
 u'entry.language': 354,
 u'entry.links': 18734,
 u'entry.media.urls': 18734,
 u'entry.published': 18492,
 u'entry.publisher': 129,
 u'entry.summary': 18658,
 u'entry.tags.scheme': 8045,
 u'entry.tags.term': 14142,
 u'entry.title': 18734,
 u'entry.updated': 1871}
Total feed entries: 18734&lt;/pre&gt;&lt;i&gt;Примечание&lt;/i&gt;: напротив каждого поля указывается число повторений его в структуре для 18 тыс новостей&lt;br /&gt;
&lt;br /&gt;
В качестве аргументов для SimpleFeed передается исходный словарь и “черный” список полей, которые при обработке будут отбрасываться. Метод handle() возвращает результируюший “плоский словарь”. &lt;br /&gt;
&lt;pre&gt;simple_feed = pysimplefeed.SimpleFeed(entry).handle()&lt;/pre&gt;По умолчанию, “черный” список полей можно не указывать, тогда при обработке будут использованы поля заданные в переменной pysimplefeed.BLACK_LIST_FIELDS.&lt;br /&gt;
&lt;br /&gt;
Детально по каждому из полей, возвращаемых по SimpleFeed(...).handle()&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;entry.authors&lt;/b&gt;&lt;br /&gt;
список авторов новости. Для каждого автора формируется словарь из полей name (имя автора), href (ссылка на веб сайт), email. Заполняется в зависимости от информации содержашейся в исходных данных&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;entry.title&lt;/b&gt;&lt;br /&gt;
заголовок новости&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;entry.comments&lt;/b&gt;&lt;br /&gt;
ссылка на комментарии к новости&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;entry.content.subtitle&lt;/b&gt;&lt;br /&gt;
дополнительная информация для заголовка новости&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;entry.content.html&lt;/b&gt;&lt;br /&gt;
текст новости в формате HTML&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;entry.content.text&lt;/b&gt;&lt;br /&gt;
новость в тектовом формате&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;entry.content.xml&lt;/b&gt;&lt;br /&gt;
текст новости в формате XML&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;entry.content.rights&lt;/b&gt;&lt;br /&gt;
информация об авторских правах на новость&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;entry.edited&lt;/b&gt;&lt;br /&gt;
дата и время последней редакции&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;entry.language&lt;/b&gt;&lt;br /&gt;
язык на котором написана новость&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;entry.links&lt;/b&gt;&lt;br /&gt;
список ссылок. Первая ссылка simple_feed[u’entry.links’][0] содержит линк на саму новость. Может быть использована для проверки уникальности в базе данных&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;entry.media.urls&lt;/b&gt;&lt;br /&gt;
список ссылок на медиа данные: изображения, видео, аудо материалы&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;entry.published&lt;/b&gt;&lt;br /&gt;
дата и время публикации&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;entry.publisher&lt;/b&gt;&lt;br /&gt;
издатель&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;entry.summary&lt;/b&gt;&lt;br /&gt;
краткое описание новости&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;entry.tags.term&lt;/b&gt;&lt;br /&gt;
список тегов к новости&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;entry.tags.scheme&lt;/b&gt;&lt;br /&gt;
описание схем для тегов&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;entry.updated&lt;/b&gt;&lt;br /&gt;
дата и время обновления новости&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2025136836330523605-2823727670787880894?l=devel.ownport.net' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/develforfun/~4/xU3HkI5b6SM" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://devel.ownport.net/feeds/2823727670787880894/comments/default" title="Комментарии к сообщению" /><link rel="replies" type="text/html" href="http://devel.ownport.net/2012/03/pysimplefeed-rss.html#comment-form" title="Комментарии: 0" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/2025136836330523605/posts/default/2823727670787880894?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/2025136836330523605/posts/default/2823727670787880894?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/develforfun/~3/xU3HkI5b6SM/pysimplefeed-rss.html" title="PySimpleFeed: компактное представление структуры RSS новостей" /><author><name>d.rey</name><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://2.bp.blogspot.com/-snKr7NfoYvc/S-Bs2snY0uI/AAAAAAAAAJA/ITWeo5zc5DE/s72-c/100px-Feed-icon.svg.png" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://devel.ownport.net/2012/03/pysimplefeed-rss.html</feedburner:origLink></entry><entry gd:etag="W/&quot;D0YMRXw9eyp7ImA9WhVQEEo.&quot;"><id>tag:blogger.com,1999:blog-2025136836330523605.post-9154412471062069457</id><published>2012-03-29T22:22:00.000+03:00</published><updated>2012-03-30T05:39:44.263+03:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-03-30T05:39:44.263+03:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="data" /><category scheme="http://www.blogger.com/atom/ns#" term="structure" /><category scheme="http://www.blogger.com/atom/ns#" term="python" /><category scheme="http://www.blogger.com/atom/ns#" term="complex" /><category scheme="http://www.blogger.com/atom/ns#" term="rss" /><title>Простое представление словарей со сложной структурой</title><content type="html">Словари со сложной внутренней структурой могут содержать различные типы данных от вложенных словарей до списков, содержащих опять же вложенные словари или другие, произвольные типы данных. Примером таких словарей является структура RSS ленты, возвращаемая библиотекой &lt;a href="http://code.google.com/p/feedparser/"&gt;Universal Feed Parser&lt;/a&gt; по feedparser.parse(). Определение структуры с множественной вложеностью данных, а тем более сравнение структур между собой может быть достаточно сложной задачей. Для упрощения этих задач можно воспользоваться небольшой функцией, выполняющей преобразование вложенных структур к “плоскому” виду - словарю, содержащему в виде ключа информацию о вложенности данных, а в виде значения - сами данные. &lt;br /&gt;
&lt;a name='more'&gt;&lt;/a&gt;&lt;pre&gt;def dict2flat(root_name, source, removeEmptyFields=False):
    ''' returns a simplified "flat" form of the complex hierarchical dictionary '''
    flat_dict = {}
    if isinstance(source, list):
        for i,e in enumerate(source):
            new_root_name = "%s[%d]" % (root_name,i)
            for k,v in dict2flat(new_root_name,e).items():
                flat_dict[k] = v
    elif isinstance(source, dict):
        for k,v in source.items():
            new_root_name = "%s.%s" % (root_name, k)
            for kk, vv in dict2flat(new_root_name,v).items():
                flat_dict[kk] = vv
    else:
        if source is not None:
            flat_dict[root_name] = source
    return flat_dict&lt;/pre&gt;В качестве параметров передаются имя корня (произвольное текстовое значение), исходный словарь, флаг, определяющий удалять поля с пустыми значениями или нет. &lt;br /&gt;
&lt;br /&gt;
Пример неполного вывода функции dict2flat(u‘entry’, entry) c агрегацией струкуры данных более сотни RSS лент выглядит следующим образом: &lt;pre&gt;{u'entry.app_control': 1,
 u'entry.app_edited': 232,
 u'entry.author': 9059,
 u'entry.author_detail.email': 605,
 u'entry.author_detail.href': 1166,
 u'entry.author_detail.name': 8989,
 u'entry.authors[0].email': 338,
 u'entry.authors[0].href': 1166,
 u'entry.authors[0].name': 1600,
 u'entry.bitrate': 25,
 u'entry.comments': 7202,
 u'entry.comments_detail.value': 1,
 u'entry.content[0].base': 3330,
 u'entry.content[0].language': 404,
 u'entry.content[0].type': 3330,
 u'entry.content[0].value': 3330,
 u'entry.content[1].base': 77,
 u'entry.content[1].type': 77,
 u'entry.content[1].value': 77,
 u'entry.dc_date.taken': 420,
 u'entry.dc_relation': 124,
 u'entry.dc_source.url': 1877,
 u'entry.dc_tags': 3765,
 u'entry.dc_tags_detail.value': 1,
 u'entry.embed': 1005,
...
u'entry.link': 17885,
 u'entry.links[0].href': 17885,
 u'entry.links[0].rel': 17885,
 u'entry.links[0].style': 1,
 u'entry.links[0].target': 1,
 u'entry.links[0].title': 365,
 u'entry.links[0].type': 17826,
 u'entry.links[10].href': 2,
…
 u'entry.tags[0].label': 355,
 u'entry.tags[0].scheme': 7654,
 u'entry.tags[0].term': 13504,
 u'entry.tags[10].label': 5,
 u'entry.tags[10].scheme': 160,
 u'entry.tags[10].term': 450,
 u'entry.tags[11].label': 5,
 u'entry.tags[11].scheme': 151,
…&lt;/pre&gt;Напротив каждого поля указывается число повторений его в структуре данных для порядка 18 тыс. RSS новостей.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2025136836330523605-9154412471062069457?l=devel.ownport.net' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/develforfun/~4/Pzz4gf8HjLE" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://devel.ownport.net/feeds/9154412471062069457/comments/default" title="Комментарии к сообщению" /><link rel="replies" type="text/html" href="http://devel.ownport.net/2012/03/blog-post.html#comment-form" title="Комментарии: 0" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/2025136836330523605/posts/default/9154412471062069457?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/2025136836330523605/posts/default/9154412471062069457?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/develforfun/~3/Pzz4gf8HjLE/blog-post.html" title="Простое представление словарей со сложной структурой" /><author><name>d.rey</name><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>0</thr:total><feedburner:origLink>http://devel.ownport.net/2012/03/blog-post.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DkAFRX4ycCp7ImA9WhVXF08.&quot;"><id>tag:blogger.com,1999:blog-2025136836330523605.post-4045514320304081239</id><published>2012-03-11T08:38:00.000+02:00</published><updated>2012-04-18T07:51:54.098+03:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-04-18T07:51:54.098+03:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="kvlite2" /><category scheme="http://www.blogger.com/atom/ns#" term="fetch" /><category scheme="http://www.blogger.com/atom/ns#" term="daemon" /><category scheme="http://www.blogger.com/atom/ns#" term="python" /><category scheme="http://www.blogger.com/atom/ns#" term="feedparser" /><category scheme="http://www.blogger.com/atom/ns#" term="rss" /><title>rssfetch, новые возможности</title><content type="html">&lt;a href="http://2.bp.blogspot.com/-snKr7NfoYvc/S-Bs2snY0uI/AAAAAAAAAJA/ITWeo5zc5DE/s1600/100px-Feed-icon.svg.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://2.bp.blogspot.com/-snKr7NfoYvc/S-Bs2snY0uI/AAAAAAAAAJA/ITWeo5zc5DE/s1600/100px-Feed-icon.svg.png" /&gt;&lt;/a&gt;Со времени публикации последнего поста “&lt;a href="http://devel.ownport.net/2012/03/rss-rssfetch.html"&gt;Загрузчик RSS лент (rssfetch)&lt;/a&gt;”, rssfetch обзавелся рядом дополнений и ноововведений:&lt;br /&gt;
- изменена структура помощи и работа с командной строкой&lt;br /&gt;
- добавлены функции логирования работы с возможностью вывода как на консоль, так и запись в файл&lt;br /&gt;
- добавлена возможность запуска как сервиса&lt;br /&gt;
&lt;a name='more'&gt;&lt;/a&gt;&lt;br /&gt;
Для вызова помощи достаточно указать аргумент -h или --help&lt;pre&gt;$ python rssfetch.py --help
usage: rssfecth &amp;lt;options&amp;gt;
author: Andrey Usov &amp;lt;http://devel.ownport.net&amp;gt;, version: 0.2
Options:
 -h, --help   print this help
 -i, --import=&amp;lt;json_file&amp;gt; import feeds from json file
 -s, --show_feeds  show feeds details
 -l, --logfile   logging to file
 -u, --update_entries  run periodical feed entries update
 -d, --daemon   run periodical feed entries update as service&lt;/pre&gt;Импорт новых RSS лент и вывод детальной информации о них не изменился, изменились только аргументы командной строки. Теперь поддерживаются короткие ключи.&lt;br /&gt;
&lt;br /&gt;
Ранее логирование выполнялось только на стандартный вывод, сейчас при указании ключа -i или --logfile вывод сообщений можно направить в файл&lt;pre&gt;$ python rssfetch.py -u --logfile=rssfetch.log&lt;/pre&gt;Запуск обновлений постов можно выполнять двумя путями: как приложение или как сервис. При запуске как приложения, rssfetch будет выполняться свою работу до тех пор пока окно в котором он запущен rssfetch не будет закрыто или пока пользователь сам не остановит его работу нажатие Ctrl+C. &lt;pre&gt;$ python rssfetch.py -u &lt;/pre&gt;При запуске rssfetсh как сервис такая зависимость исчезает. &lt;pre&gt;$ python rssfetch.py -u -d -l rssfetch.log &lt;/pre&gt;Для того, чтобы запустить rssfetch как сервис необходимо в файле конфигурации settings.py прописать абсолютный путь к PID файлу - тестовый файл содержащий номер процесса rssfetch, формируется автоматически при запуске.&lt;br /&gt;
&lt;br /&gt;
Для остановки процесса необходимо выполнить&lt;pre&gt;$kill `cat rssfetch.pid`&lt;/pre&gt;Иногда не совсем удобно, когда запускаемые файлы  и библиотеки для работы с приложением расположены в одной директории. Проще работать с один файлом. Тогда его можно перенести в bin директорию не боясь создать мешанину из скриптов и библиотек. Python поддерживает запуск приложения прямо из zip файла. Выполнив настройки rssfetch в settings.py файле можно запаковать все необходимые файлы в один архив rssfetch.zip. Список файлов ниже:&lt;pre&gt;feedparser.py
kvlite2.py
rssfetch.py
settings.py
__main__.py&lt;/pre&gt;Теперь rssfetch можно запустить прямо из zip файла&lt;pre&gt;$ python rssfetch.zip --help

usage: rssfecth &amp;lt;options&amp;gt;
author: Andrey Usov &amp;lt;http://devel.ownport.net&amp;gt;, version: 0.2
Options:
 -h, --help   print this help
 -i, --import=&amp;lt;json_file&amp;gt; import feeds from json file
 -s, --show_feeds  show feeds details
 -l, --logfile   logging to file
 -u, --update_entries  run periodical feed entries update
 -d, --daemon   run periodical feed entries update as service&lt;/pre&gt;Загрузить версию rssfetch 0.2 можно с &lt;a href="http://code.google.com/p/sources-ownport/downloads/list"&gt;http://code.google.com/p/sources-ownport/&lt;/a&gt;&lt;br /&gt;
Исходный код доступен в репозиториии &lt;a href="http://code.google.com/p/sources-ownport/source/browse/rssfetch"&gt;http://code.google.com/p/sources-ownport/&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2025136836330523605-4045514320304081239?l=devel.ownport.net' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/develforfun/~4/SZPWRkHn6ns" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://devel.ownport.net/feeds/4045514320304081239/comments/default" title="Комментарии к сообщению" /><link rel="replies" type="text/html" href="http://devel.ownport.net/2012/03/rssfetch.html#comment-form" title="Комментарии: 0" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/2025136836330523605/posts/default/4045514320304081239?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/2025136836330523605/posts/default/4045514320304081239?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/develforfun/~3/SZPWRkHn6ns/rssfetch.html" title="rssfetch, новые возможности" /><author><name>d.rey</name><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://2.bp.blogspot.com/-snKr7NfoYvc/S-Bs2snY0uI/AAAAAAAAAJA/ITWeo5zc5DE/s72-c/100px-Feed-icon.svg.png" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://devel.ownport.net/2012/03/rssfetch.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DU8BQHw-fyp7ImA9WhVSFEk.&quot;"><id>tag:blogger.com,1999:blog-2025136836330523605.post-1239124091641475968</id><published>2012-03-09T09:22:00.001+02:00</published><updated>2012-03-11T08:37:31.257+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-03-11T08:37:31.257+02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="kvlite2" /><category scheme="http://www.blogger.com/atom/ns#" term="fetch" /><category scheme="http://www.blogger.com/atom/ns#" term="python" /><category scheme="http://www.blogger.com/atom/ns#" term="feedparser" /><category scheme="http://www.blogger.com/atom/ns#" term="rss" /><title>Загрузчик RSS лент (rssfetch)</title><content type="html">&lt;a href="http://2.bp.blogspot.com/-snKr7NfoYvc/S-Bs2snY0uI/AAAAAAAAAJA/ITWeo5zc5DE/s1600/100px-Feed-icon.svg.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://2.bp.blogspot.com/-snKr7NfoYvc/S-Bs2snY0uI/AAAAAAAAAJA/ITWeo5zc5DE/s1600/100px-Feed-icon.svg.png" /&gt;&lt;/a&gt;Данным постом начинается небольшая серия статей по созданию загрузчика RSS лент с использованием &lt;a href="http://code.google.com/p/feedparser/"&gt;Universal Feed Parser&lt;/a&gt; и &lt;a href="http://code.google.com/p/kvlite/"&gt;KVLite2&lt;/a&gt;. Основная задача: периодическая проверка наличия новых постов для выбранных RSS лент и хранение их в базе данных для последующей обработки. &lt;br /&gt;
&lt;br /&gt;
Для начала работы необходимо создать новую базу данных в MySQL - rssfetch и пользователя, который будет работать с этой базой данных - rssfetch.&lt;br /&gt;
&lt;pre&gt;mysql&amp;gt; create database rssfetch;
Query OK, 1 row affected (0.03 sec)
mysql&amp;gt; grant all privileges on rssfetch.* to 'rssfetch'@'localhost' identified by '&amp;lt;ваш пароль&amp;gt;';
Query OK, 0 rows affected (0.10 sec)&lt;/pre&gt;&lt;a name='more'&gt;&lt;/a&gt;Название базы данных и имя пользователя могут быть произвольными. “rssfetch” взят как пример.&lt;br /&gt;
&lt;br /&gt;
Для созданной базы данных и пользователя необходимо прописать настройки в файле конфигурации settings.py &lt;br /&gt;
&lt;pre&gt;FEEDS_URI = "mysql://rssfetch:&amp;lt;ваш пароль&amp;gt;@localhost/rssfetch.feeds"
ENTRIES_URI = "mysql://rssfetch:&amp;lt;ваш пароль&amp;gt;@localhost/rssfetch.entries"
USER_AGENT = 'rssfetcher/0.1'
SERVER_RESPONSE_TIMEOUT = 60    # time for waiting response from the server
TIME_INTERVAL = 1800 # seconds, 30 minutes. Waiting time for the next update&lt;/pre&gt;&lt;ul&gt;&lt;li&gt;FEEDS_URI и ENTRIES_FEED параметры описывают параметры доступа к коллекциям RSS лент и постам.&lt;/li&gt;
&lt;li&gt;USER_AGENT параметр позволяет изменить значение по умолчанию, определяемое в feedparser &lt;a href="http://ru.wikipedia.org/wiki/User_Agent"&gt;http://ru.wikipedia.org/wiki/User_Agent&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;SERVER_RESPONSE_TIMEOUT определяет в секундах время ожидания ответа от сервера&lt;/li&gt;
&lt;li&gt;TIME_INTERVAL определяет в секундах время между циклами обновления RSS лент&lt;/li&gt;
&lt;/ul&gt;Для начала работы rssfetch необходимо загрузить информацию о RSS лентах. Загрузка выполняется из JSON файла: &lt;br /&gt;
&lt;pre&gt;# python rssfetch.py import &amp;lt;json_file&amp;gt;&lt;/pre&gt;Формат файла имеет следующую структуру: &lt;br /&gt;
&lt;pre&gt;[
    {   "title": "MySQL Performance Blog",         
        "text": "MySQL Performance Blog. Percona's MySQL &amp; InnoDB performance and scalability blog",         
        "xmlUrl": "http://www.mysqlperformanceblog.com/feed/",
        "htmlUrl": "http://www.mysqlperformanceblog.com/" }
]&lt;/pre&gt;Обязательным полем является xmlUrl, указывающее на RSS ленту. Оно определяет уникальность записей в базе данных. Повторная попытка импортировать в базу новую RSS ленту с уже существующим xmlUrl будет проигнорирована. Остальные поля являются вспомогательными и не влияют на работу rssfetch. Описание ленты не ограничено только этими полями, можно добавлять любые поля по необходимости. Данные по RSS лентам хранятся в таблице rssfetch.feeds&lt;br /&gt;
&lt;br /&gt;
Для вывода списка импортированных  RSS лент &lt;br /&gt;
&lt;pre&gt;# python rssfetch.py show_feeds
...
id: 108, key: fb4805703b327adbd176377a5fba6b6b3e129c8c
details: {u'xmlUrl': u'http://www.mysqlperformanceblog.com/feed/', u'text': u"MySQL Performance Blog. Percona's MySQL &amp;amp; InnoDB performance and scalability blog", u'htmlUrl': u'http://www.mysqlperformanceblog.com/', u'title': u'MySQL Performance Blog'}
...&lt;/pre&gt;&lt;ul&gt;&lt;li&gt;id - порядковый номер RSS ленты в базе данных,&lt;/li&gt;
&lt;li&gt;key - идентификатор RSS ленты, рассчитывается как функция sha1 от поля xmlUrl  hashlib.sha1(feed['xmlUrl']).hexdigest()&lt;/li&gt;
&lt;li&gt;details - детальное описание RSS ленты&lt;/li&gt;
&lt;/ul&gt;Обновление данных для RSS лент выполняется с помощью команды &lt;pre&gt;# python rssfetch.py update_entries
…
2012-03-09 08:02:22 feed: http://www.mysqlperformanceblog.com/feed/ (total: 10, new: 0)
…&lt;/pre&gt;После выполнения команды запускается периодический процесс обновления данных RSS лент в порядке их импорта в базу данных. Периодичность проверки новых постов определяется параметром settings.TIME_INTERVAL. Лог выполнения пишется в стандартный вывод. Для каждой ленты отображается краткая информация: дата и время обновления, ссылка на RSS ленту, общее число загруженных постов и количество новых. &lt;br /&gt;
&lt;br /&gt;
rssfetch умеет оперировать значением &lt;a href="http://en.wikipedia.org/wiki/HTTP_ETag"&gt;ETag&lt;/a&gt;, позволяя тем самым более эффективно использовать ресурсы как сервера, так и пропускной способности канала между сервером и rssfetch. Значение ETag сохраняется после каждого обращения к серверу и при повторном обращении передается в запросе. Для корректной работы этой функциональности сервер должен уметь работать с полем ETag.&lt;br /&gt;
&lt;br /&gt;
По окончании каждого цикла в лог записывает общая информация о количестве проверенных лент, числе новых записей и общем времени обновления. &lt;pre&gt;2012-03-09 08:02:22 rssfetch: total feeds: 109, new entries: 2, feeds update time 0:03:10.687371&lt;/pre&gt;Загрузить версию rssfetch 0.1 можно с &lt;a href="http://code.google.com/p/sources-ownport/downloads/list"&gt;http://code.google.com/p/sources-ownport/&lt;/a&gt;&lt;br /&gt;
Исходный код доступен в репозиториии &lt;a href="http://code.google.com/p/sources-ownport/source/browse/rssfetch"&gt;http://code.google.com/p/sources-ownport/&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2025136836330523605-1239124091641475968?l=devel.ownport.net' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/develforfun/~4/396w4jGrcHQ" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://devel.ownport.net/feeds/1239124091641475968/comments/default" title="Комментарии к сообщению" /><link rel="replies" type="text/html" href="http://devel.ownport.net/2012/03/rss-rssfetch.html#comment-form" title="Комментарии: 0" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/2025136836330523605/posts/default/1239124091641475968?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/2025136836330523605/posts/default/1239124091641475968?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/develforfun/~3/396w4jGrcHQ/rss-rssfetch.html" title="Загрузчик RSS лент (rssfetch)" /><author><name>d.rey</name><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://2.bp.blogspot.com/-snKr7NfoYvc/S-Bs2snY0uI/AAAAAAAAAJA/ITWeo5zc5DE/s72-c/100px-Feed-icon.svg.png" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://devel.ownport.net/2012/03/rss-rssfetch.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CEAMSX4yeSp7ImA9WhVTGEg.&quot;"><id>tag:blogger.com,1999:blog-2025136836330523605.post-7072542768748810264</id><published>2012-03-04T09:38:00.000+02:00</published><updated>2012-03-04T11:19:48.091+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-03-04T11:19:48.091+02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="download" /><category scheme="http://www.blogger.com/atom/ns#" term="url" /><category scheme="http://www.blogger.com/atom/ns#" term="fetch" /><category scheme="http://www.blogger.com/atom/ns#" term="python" /><category scheme="http://www.blogger.com/atom/ns#" term="html" /><title>Расширенный urlfetch</title><content type="html">&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/-TKTTGS3e3wg/T1MZikqDwpI/AAAAAAAAAfU/ne72nQPY2Wg/s1600/addressbar.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="113" src="http://3.bp.blogspot.com/-TKTTGS3e3wg/T1MZikqDwpI/AAAAAAAAAfU/ne72nQPY2Wg/s320/addressbar.png" width="150" /&gt;&lt;/a&gt;&lt;/div&gt;О способах получения данных из интернет уже упоминалось несколько раз. Предыдущие примеры позволяли на базе простых функций, компонент или процессов загружать тестовую информации из интернет-ресурсов. Некоторые из них, позволяли просто загружать данные, другие выполнять загрузку последовательно на основании списка, некоторые параллельно. За время использования предыдущих версий стало понятно, что только отправка HTTP GET и получения данных не всегда является достаточным, а некоторых случаях просто не эффективно. Необходим подход позволяющий более эффективно осуществлять запросы с серверам и обрабатывать полученные данные. Решение пришло неожиданно и как это всегда бывает - лежало перед носом. &lt;a href="http://code.google.com/p/feedparser/"&gt;Universal Feed Parser&lt;/a&gt; - это отличный модуль, написанный на python, позволяющий загружать и обрабатывать RSS ленты различных форматов.&lt;br /&gt;
&lt;a name='more'&gt;&lt;/a&gt;&lt;br /&gt;
Модуль &lt;a href="http://code.google.com/p/sources-ownport/wiki/UrlFetch"&gt;urlfetch&lt;/a&gt; является пеработкой feedparser-а. Основной акцент делается на загрузку текстовых данных, поэтому код специфичный для работы с RSS/Atom лентами был убран. Из-за этого упростились многие функции, например, такие как определение кодировки данных на основании содержимого. Как и feedparser, так и urlfetch достаточно легок в использовании. Модуль не зависим от сторонних библиотек, поэтому может работать на базовом python версии 2.4 и выше (на python 3 не тестировался). Для экспериментов  включена поддержка работы из командной строки:&lt;br /&gt;
&lt;pre&gt;#python urlfetch.py &amp;lt;URL&amp;gt;&lt;/pre&gt;Результатом выполнения будет вывод на экран словаря, содержащего две секции - полей заголовка (headers) и собственно само содержимое страницы (body). Для интеграции urlfetch в приложение используется единственная функция urlfetch.fetch() &lt;br /&gt;
&lt;pre&gt;def fetch(url, etag=None, modified=None, agent=None, referrer=None, handlers=[], request_headers={}, absolute_urls=False)&lt;/pre&gt;которая возвращает словарь, состоящий из заголовка и содержимого страницы. Описание и примеры использования приведены на wiki странице модуля &lt;a href="http://code.google.com/p/sources-ownport/wiki/UrlFetch"&gt;urlfetch&lt;/a&gt;, поэтому ниже опишу лишь возможности реализованные в текущей версии:&lt;br /&gt;
&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;поддержка &lt;a href="http://en.wikipedia.org/wiki/HTTP_ETag"&gt;ETag&lt;/a&gt;, позволяет использовать один из механизмов работы с кешем web страниц на стороне сервера, сохраняя пропускную способность и ресурсы сервера. Клиент посылая запрос с значением ETag поля, полученным в прошлом запросе, дает возможность серверу оценить необходимость отправки запрашиваемой информации повторно. Если данные на стороне сервера не изменились  с последнего обращения, сервер возвращает ответ с &lt;a href="http://en.wikipedia.org/wiki/HTTP_304#3xx_Redirection"&gt;HTTP 304&lt;/a&gt; &amp;nbsp;без передачи самого содержимого ресурса - указывая на то, что данные не изменены.&lt;/li&gt;
&lt;li&gt;поддержка &lt;a href="http://en.wikipedia.org/wiki/List_of_HTTP_header_fields"&gt;Last-Modified&lt;/a&gt;. Это второй механизм, поддерживаемый urlfetch для работы с кеширующими серверами. В отличии от ETag, передается дата и время последнего изменения ресурса.&lt;/li&gt;
&lt;li&gt;поддержка User-Agent. По умолчанию urlfetch передает строку “UrlFetch/0.1 +http://code.google.com/p/sources-ownport”. Если вы встраиваете urlfetch в свое приложение, вы должны изменить значение User-Agent на свое, согласно правилам &lt;a href="http://en.wikipedia.org/wiki/User_agent"&gt;http://en.wikipedia.org/wiki/User_agent&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;поддержка &lt;a href="http://en.wikipedia.org/wiki/HTTP_referrer"&gt;HTTP Referrer&lt;/a&gt;, адрес web страницы с которой осуществлено обращение к запрашиваемой странице.&lt;/li&gt;
&lt;li&gt;поддержка пользовательских обработчиков используемых в &lt;a href="http://docs.python.org/library/urllib2.html#urllib2.build_opener"&gt;urllib2.build_opener&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;поддержка переопределения значений по умолчанию в HTTP запросах на пользовательские&lt;/li&gt;
&lt;li&gt;автоматическое преобразование содержимого станицы в UTF-8 кодировку на основании информации переданной сервером в HTTP заголовке (content-type, charset)&lt;/li&gt;
&lt;li&gt;возможность преобразование относительных ссылок внутри содержимого страницы на абсолютные, например ссылка “/2012/02/mysql.html” будет заменена на “http://devel.ownport.net/2012/02/mysql.html”&lt;/li&gt;
&lt;/ul&gt;&lt;br /&gt;
Исходный код модуля urlfetch доступен на &lt;a href="http://code.google.com/p/sources-ownport/source/browse/urlfetch"&gt;http://code.google.com/p/sources-ownport/&lt;/a&gt;&lt;br /&gt;
&lt;a href="http://code.google.com/p/sources-ownport/wiki/UrlFetch"&gt;Wiki страница с описанием работы&lt;/a&gt;&lt;br /&gt;
Изображение адресной строки взято с сайта &lt;a href="http://www.freedigitalphotos.net/images/view_photog.php?photogid=659"&gt;www.freedigitalphotos.net, автор Salvatore Vuono&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2025136836330523605-7072542768748810264?l=devel.ownport.net' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/develforfun/~4/5WPKqrI_5Kg" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://devel.ownport.net/feeds/7072542768748810264/comments/default" title="Комментарии к сообщению" /><link rel="replies" type="text/html" href="http://devel.ownport.net/2012/03/urlfecth.html#comment-form" title="Комментарии: 0" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/2025136836330523605/posts/default/7072542768748810264?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/2025136836330523605/posts/default/7072542768748810264?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/develforfun/~3/5WPKqrI_5Kg/urlfecth.html" title="Расширенный urlfetch" /><author><name>d.rey</name><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://3.bp.blogspot.com/-TKTTGS3e3wg/T1MZikqDwpI/AAAAAAAAAfU/ne72nQPY2Wg/s72-c/addressbar.png" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://devel.ownport.net/2012/03/urlfecth.html</feedburner:origLink></entry><entry gd:etag="W/&quot;C0cAQ3c7cCp7ImA9WhVTGUk.&quot;"><id>tag:blogger.com,1999:blog-2025136836330523605.post-4517965671262340109</id><published>2012-02-25T22:44:00.000+02:00</published><updated>2012-03-05T11:50:42.908+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-03-05T11:50:42.908+02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="mysql" /><category scheme="http://www.blogger.com/atom/ns#" term="kvlite" /><category scheme="http://www.blogger.com/atom/ns#" term="key-value" /><category scheme="http://www.blogger.com/atom/ns#" term="python" /><category scheme="http://www.blogger.com/atom/ns#" term="nosql" /><category scheme="http://www.blogger.com/atom/ns#" term="database" /><title>MySQL как база данных ключ/значение</title><content type="html">&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/-oVy40xLPbnM/T0lHC5YcYUI/AAAAAAAAAfI/HLAHIpWeLcA/s1600/nosql-or-notonlysql.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://3.bp.blogspot.com/-oVy40xLPbnM/T0lHC5YcYUI/AAAAAAAAAfI/HLAHIpWeLcA/s1600/nosql-or-notonlysql.png" /&gt;&lt;/a&gt;&lt;/div&gt;Специализированных решений для хранения ключ/значений достаточно много, достаточно взглянуть на &lt;a href="http://en.wikipedia.org/wiki/NoSQL"&gt;страницу wikipedia NoSQL&lt;/a&gt;. С учетом того, что подход NoSQL относительно нов, по сравнению с реляционными базами данных, с каждым днем он набирает все больше и больше сторонников. К сожалению, не всегда есть возможность выделить отдельный сервер или установить необходимое программное обеспечения для работы с NoSQL базами данных. Но в то же время, базы данных MySQL доступны практически у любого хостинг-провайдера, есть сборки  mysql не требующие установки, руководств и советов по mysql можно найти значительно больше, чем для любой другой базы данных. Попытки найти некий баланс привели к созданию &lt;a href="http://code.google.com/p/kvlite/"&gt;небольшой библиотеки KVLite2&lt;/a&gt;.&lt;br /&gt;
&lt;a name='more'&gt;&lt;/a&gt;&lt;br /&gt;
KVLite2 - это небольшая обвертка на python (около 200 строк кода), позволяющая хранить данные ключ/значение в базе данных MySQL. Для работы достаточно одного файла &lt;a href="http://kvlite.googlecode.com/hg/kvlite2.py"&gt;kvlite2.py&lt;/a&gt;. По своей логике работы KVLite2 больше близка к &lt;a href="http://www.mongodb.org/"&gt;MongoDB&lt;/a&gt;. Она оперирует документами и коллекциями документов. Ключи используются для быстрого доступа к документам. В посте не стану описывать принципы работы библиотеки, я постарался описать все важные аспекты и примеры работы в небольшом руководстве по работе с KVLite2 на &lt;a href="http://code.google.com/p/kvlite/wiki/KVLite2Tutorial"&gt;Wiki проекта&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Важно&lt;/b&gt;: изначально планировалось использовать библиотеку cjson, как наиболее быструю в обработке JSON формата. Но в связи с обнаружнными ошибками в работе, использование cjson следует избегать и использовать стандартную библиотеку json.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2025136836330523605-4517965671262340109?l=devel.ownport.net' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/develforfun/~4/4TLsllDr6r0" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://devel.ownport.net/feeds/4517965671262340109/comments/default" title="Комментарии к сообщению" /><link rel="replies" type="text/html" href="http://devel.ownport.net/2012/02/mysql.html#comment-form" title="Комментарии: 0" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/2025136836330523605/posts/default/4517965671262340109?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/2025136836330523605/posts/default/4517965671262340109?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/develforfun/~3/4TLsllDr6r0/mysql.html" title="MySQL как база данных ключ/значение" /><author><name>d.rey</name><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://3.bp.blogspot.com/-oVy40xLPbnM/T0lHC5YcYUI/AAAAAAAAAfI/HLAHIpWeLcA/s72-c/nosql-or-notonlysql.png" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://devel.ownport.net/2012/02/mysql.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DkUNQnY8fyp7ImA9WhVTEEg.&quot;"><id>tag:blogger.com,1999:blog-2025136836330523605.post-584780728451181767</id><published>2012-02-23T22:05:00.001+02:00</published><updated>2012-02-24T05:31:33.877+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-02-24T05:31:33.877+02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="cluster" /><category scheme="http://www.blogger.com/atom/ns#" term="erlang" /><category scheme="http://www.blogger.com/atom/ns#" term="mapreduce" /><category scheme="http://www.blogger.com/atom/ns#" term="python" /><category scheme="http://www.blogger.com/atom/ns#" term="architecture" /><category scheme="http://www.blogger.com/atom/ns#" term="disco" /><title>Архитектура Disco</title><content type="html">Краткое описание Disco - MapReduce системы на базе Erlang и Python было дано в одном из &lt;a href="http://devel.ownport.net/2012/02/disco-mapreduce.html"&gt;предыдущих постов&lt;/a&gt;.  Несколько слов об архитектуре.&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/-p02aoofhc9w/T0abPjh0KtI/AAAAAAAAAe8/XhpUANcSzLQ/s1600/disco-architecture.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="183" src="http://3.bp.blogspot.com/-p02aoofhc9w/T0abPjh0KtI/AAAAAAAAAe8/XhpUANcSzLQ/s400/disco-architecture.png" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;
Disco основана на архитектура главный-ведомый (master-slave).&lt;br /&gt;
&lt;a name='more'&gt;&lt;/a&gt;&lt;ul&gt;&lt;li&gt;Клиентские приложения передают системе задачи для выполнения через мастер-ноду (master)&lt;/li&gt;
&lt;li&gt;Мастер-нода (master) получает задачи, добавляет их в очередь и запускает их на нодах кластера (slave), как только те становятся свободными.&lt;/li&gt;
&lt;li&gt;Ведомые ноды кластера (slave) запускаются мастер-нодой, они активируют и осуществляют мониторинг всех процессов внутри ноды самостоятельно, без участия мастер-ноды&lt;/li&gt;
&lt;li&gt;Рабочие процессы (worker) выполняют переданные мастер-нодой задачи. Местоположения результатов обработки данных передаются на мастер-ноду.&lt;/li&gt;
&lt;li&gt;Disco старается обрабатывать данные локально - назначая задачи по обработке данных на те ноды, на которых эти данные  расположены. HTTP сервер запущенный на каждой ноде позволяет получить доступ к данным для рабочих процессов, запущенных на других нодах. Это полезно в тех случаях, когда рабочий процесс, по неким причинам, не может быть запущен на той же ноде, где расположены данные.&lt;/li&gt;
&lt;li&gt;Пользователь может ограничивать количество параллельно запущенных рабочих процессов равным числу процессоров, дисков ноды или определить произвольное число параллельных процессов.&lt;/li&gt;
&lt;/ul&gt;Если необходима высокая доступность системы, существует возможность организации несколько мастер-нод. Это позволяет устранить проблему единой точки сбоя - выхода из строя мастер-ноды.&lt;br /&gt;
&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2025136836330523605-584780728451181767?l=devel.ownport.net' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/develforfun/~4/SIr5SUmcT1k" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://devel.ownport.net/feeds/584780728451181767/comments/default" title="Комментарии к сообщению" /><link rel="replies" type="text/html" href="http://devel.ownport.net/2012/02/disco.html#comment-form" title="Комментарии: 0" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/2025136836330523605/posts/default/584780728451181767?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/2025136836330523605/posts/default/584780728451181767?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/develforfun/~3/SIr5SUmcT1k/disco.html" title="Архитектура Disco" /><author><name>d.rey</name><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://3.bp.blogspot.com/-p02aoofhc9w/T0abPjh0KtI/AAAAAAAAAe8/XhpUANcSzLQ/s72-c/disco-architecture.png" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://devel.ownport.net/2012/02/disco.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CEENQ3w4fip7ImA9WhRaGEU.&quot;"><id>tag:blogger.com,1999:blog-2025136836330523605.post-8969224632431674816</id><published>2012-02-21T21:34:00.000+02:00</published><updated>2012-02-22T05:51:32.236+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-02-22T05:51:32.236+02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="cluster" /><category scheme="http://www.blogger.com/atom/ns#" term="mapreduce" /><category scheme="http://www.blogger.com/atom/ns#" term="architecture" /><category scheme="http://www.blogger.com/atom/ns#" term="google" /><category scheme="http://www.blogger.com/atom/ns#" term="hadoop" /><title>Статья о Google MapReduce &amp; Hadoop</title><content type="html">&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://4.bp.blogspot.com/-vSsHk4ZNpEU/Tg0_Pt6HrFI/AAAAAAAAAYQ/AYa1trgZgPg/s1600/google-logo.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://4.bp.blogspot.com/-vSsHk4ZNpEU/Tg0_Pt6HrFI/AAAAAAAAAYQ/AYa1trgZgPg/s1600/google-logo.png" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;a href="http://www.ict.edu.ru/ft/005652/62329e1-st16.pdf"&gt;Интересная статья&lt;/a&gt; о технологиях, позволяющих организовать распределенное хранение и параллельную обработку больших объемов данных в крупномасштабных кластерных системах на базе технологий Google File System (GFS), Hadoop File System (HDFS), Google BigTable, HBase, модели программирования MapReduce, Apache Hadoop, Microsoft Dryad, Chubby, ZooKeeper.  &lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://4.bp.blogspot.com/-wUFlL-5IbUs/TIxO0rtpxOI/AAAAAAAAAQg/nLMBpXvcR0M/s1600/hadoop-logo.jpg" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"&gt;&lt;img border="0" height="46" src="http://4.bp.blogspot.com/-wUFlL-5IbUs/TIxO0rtpxOI/AAAAAAAAAQg/nLMBpXvcR0M/s200/hadoop-logo.jpg" width="200" /&gt;&lt;/a&gt;&lt;/div&gt;
Речь идет о петабайтах данных, для хранения и обработки которых необходимы значительные вычислительные ресурсы. В качестве таких ресурсов рассматриваются кластерные системы, состоящие из тысяч серверов. В подобных распределенных системах остро стоят вопросы обеспечения отказоустойчивости и бесперебойного функционирования сервисов хранения и обработки данных. В таких системах важной проблемой является создание высокоуровневой модели программирования процессов обработки данных. В статье приводится описание оригинальных технологий Google, а также проводится параллель с существующими open source проектами - аналогами данных технологий, Apache Hadoop. Материал статьи подготовлен в рамках Всероссийского конкурсного отбора обзорно-аналитических статей по приоритетному направлению "&lt;a href="http://www.ict.edu.ru/itkonkurs2008/"&gt;Информационно-телекоммуникационные системы&lt;/a&gt;". &lt;br /&gt;
&lt;br /&gt;
&lt;a href="http://www.ict.edu.ru/ft/005652/62329e1-st16.pdf"&gt;Новые технологии распределенного хранения и обработки больших массивов данных&lt;/a&gt;. О.В. Сухорослов. Институт системного анализа РАН &lt;br /&gt;
&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2025136836330523605-8969224632431674816?l=devel.ownport.net' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/develforfun/~4/6R0FopxorE0" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://devel.ownport.net/feeds/8969224632431674816/comments/default" title="Комментарии к сообщению" /><link rel="replies" type="text/html" href="http://devel.ownport.net/2012/02/google-mapreduce-hadoop.html#comment-form" title="Комментарии: 0" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/2025136836330523605/posts/default/8969224632431674816?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/2025136836330523605/posts/default/8969224632431674816?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/develforfun/~3/6R0FopxorE0/google-mapreduce-hadoop.html" title="Статья о Google MapReduce &amp; Hadoop" /><author><name>d.rey</name><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://4.bp.blogspot.com/-vSsHk4ZNpEU/Tg0_Pt6HrFI/AAAAAAAAAYQ/AYa1trgZgPg/s72-c/google-logo.png" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://devel.ownport.net/2012/02/google-mapreduce-hadoop.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CEMBSHc6eCp7ImA9WhRaFks.&quot;"><id>tag:blogger.com,1999:blog-2025136836330523605.post-2708648654200814541</id><published>2012-02-19T13:50:00.001+02:00</published><updated>2012-02-19T16:40:59.910+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-02-19T16:40:59.910+02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="server" /><category scheme="http://www.blogger.com/atom/ns#" term="nokia" /><category scheme="http://www.blogger.com/atom/ns#" term="cluster" /><category scheme="http://www.blogger.com/atom/ns#" term="erlang" /><category scheme="http://www.blogger.com/atom/ns#" term="mapreduce" /><category scheme="http://www.blogger.com/atom/ns#" term="python" /><category scheme="http://www.blogger.com/atom/ns#" term="processing" /><category scheme="http://www.blogger.com/atom/ns#" term="computing" /><title>Disco - mapreduce для распределенных вычислений</title><content type="html">&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/-kuSavqbDcos/T0DP0Ip8pOI/AAAAAAAAAew/qsrmf_Ytdq0/s1600/discotext.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://3.bp.blogspot.com/-kuSavqbDcos/T0DP0Ip8pOI/AAAAAAAAAew/qsrmf_Ytdq0/s1600/discotext.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;a href="http://discoproject.org/"&gt;Disco&lt;/a&gt; - это реализация &lt;a href="http://en.wikipedia.org/wiki/MapReduce"&gt;технологии MapReduce&lt;/a&gt; для распределенный вычислений. Disco поддерживает выполнение параллельных вычислений большого объема данных, сохраненных на обычных компьютерах, включенных в кластер, реализуя идеи Google MapReduce, описанные в документе &lt;a href="http://research.google.com/archive/mapreduce.html"&gt;MapReduce: Simplified Data Processing on Large Clusters&lt;/a&gt;. Это делает Disco отличным решением для анализа и обработки больших объемов данных, не требующем дополнительных знаний в таких сложных распределенных технологиях как протоколы коммуникации, балансировка нагрузки, блокировка, распределения задач, отказоустойчивость. &lt;br /&gt;
&lt;a name='more'&gt;&lt;/a&gt;&lt;br /&gt;
Disco может быть использован для различных задач сбора, анализа данных, построения сложных вероятностных моделей, полнотекстовой индексации web-данных. И это лишь небольшой список примеров применения.&lt;br /&gt;
&lt;br /&gt;
Ядро Disco написано на &lt;a href="http://www.erlang.org/"&gt;Erlang&lt;/a&gt; - языке программирования, разработанным специально для построения масштабируемых программных систем реального времени требующих высокой доступности. Пользователи Disco обычно пишут свои задачи на Python, позволяющем описывать сложные алгоритмы небольшим и легко читаемым кодом.&lt;br /&gt;
&lt;br /&gt;
Ниже приведен рабочий пример кода для подсчета частоты использования слов в большом тексте.&lt;br /&gt;
&lt;pre&gt;from disco.core import Job, result_iterator
def map(line, params):
    for word in line.split():
        yield word, 1

def reduce(iter, params):
    from disco.util import kvgroup
    for word, counts in kvgroup(sorted(iter)):
        yield word, sum(counts)

if __name__ == '__main__':
    job = Job().run(input=["http://discoproject.org/media/text/chekhov.txt"],
                    map=map,
                    reduce=reduce)
    for word, count in result_iterator(job.wait(show=True)):
        print word, count&lt;/pre&gt;Дизайн Disco направлен на упрощение интеграции его в большие приложения, такие как web-сервисы. Существует возможность реализовать делегирование сложных вычислительных задач кластеру независимо от работы основного приложения.  Disco предоставляет невероятно компактный Python API: как правило только две функции необходимы, map и reduce.  REST Web API используется для управления задачами и web-интерфейса для мониторинга статуса работы системы.&lt;br /&gt;
&lt;br /&gt;
Disco хорошо подходит для развертывания кластеров, построенных на основе обычных Linux серверов. Новая нода может быть добавлена в систему на лету, одним кликом через web-интерфейс. Если одна из нод выходит из строя, активные задачи автоматически перераспределяются между другими нодами без прерывания работы системы. Совместно с системой автоматической инсталляции &lt;a href="http://fai-project.org/"&gt;FAI&lt;/a&gt; даже большие кластеры могут поддерживаться с минимальным количеством ручной работы. В качестве доказательства концепции, &lt;a href="http://research.nokia.com/"&gt;Центр разработки компании Nokia в Palo Alto&lt;/a&gt; обслуживает таким образом 800-ядерный Disco кластер.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Основные функциональности Disco&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;Масштабируемость на сотни процессоров и десятки тысяч параллельных задач&lt;/li&gt;
&lt;li&gt;Используется для обработки наборов данных в десятки терабайт&lt;/li&gt;
&lt;li&gt;Прост в использовании: обычные задачи содержат только две функции, написанные на python и два вызова к Disco API&lt;/li&gt;
&lt;li&gt;Задачи могут быть адаптированы под любой язык программирования через простой внешний интерфейс, базирующийся на стандартных потоках ввода-вывода.&lt;/li&gt;
&lt;li&gt;Входные данные могут быть представлены в любом формате, даже бинарные данные, такие как изображения. Данные могут быть размещены на любых ресурсах доступных через HTTP протокол или могут быть распределены на локальных дисках.&lt;/li&gt;
&lt;li&gt;Отказоустойчивость: выход из строя ноды не приводит к прерыванию выполнения задач. Новые сервера могут быть добавлены на лету.&lt;/li&gt;
&lt;li&gt;В дополнении к функциям map и reduce, есть дополнительно функции combiner и partitioner, а также функция input reader.&lt;/li&gt;
&lt;li&gt;Легкость интеграции в большие приложения используя Disco модули и Web API&lt;/li&gt;
&lt;li&gt;Поставляется со встроенной распределенной системой хранения &lt;a href="http://discoproject.org/doc/howto/ddfs.html#ddfs"&gt;Disco Distributed Filesystem&lt;/a&gt; и распределенной индексной подсистемой &lt;a href="http://discoproject.org/doc/contrib/discodex/discodex.html#discodex"&gt;Discodex&lt;/a&gt;, позволяющей выполнять специальные запросы к терабайтным данным&lt;/li&gt;
&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2025136836330523605-2708648654200814541?l=devel.ownport.net' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/develforfun/~4/PyL6hvI6kt4" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://devel.ownport.net/feeds/2708648654200814541/comments/default" title="Комментарии к сообщению" /><link rel="replies" type="text/html" href="http://devel.ownport.net/2012/02/disco-mapreduce.html#comment-form" title="Комментарии: 0" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/2025136836330523605/posts/default/2708648654200814541?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/2025136836330523605/posts/default/2708648654200814541?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/develforfun/~3/PyL6hvI6kt4/disco-mapreduce.html" title="Disco - mapreduce для распределенных вычислений" /><author><name>d.rey</name><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://3.bp.blogspot.com/-kuSavqbDcos/T0DP0Ip8pOI/AAAAAAAAAew/qsrmf_Ytdq0/s72-c/discotext.png" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://devel.ownport.net/2012/02/disco-mapreduce.html</feedburner:origLink></entry><entry gd:etag="W/&quot;C0IEQnkyeip7ImA9WhRaEkU.&quot;"><id>tag:blogger.com,1999:blog-2025136836330523605.post-7108699313158369239</id><published>2012-02-15T06:51:00.002+02:00</published><updated>2012-02-15T06:51:43.792+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-02-15T06:51:43.792+02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="data center" /><title>Дата-центр Tulip Telecom India</title><content type="html">Tulip Telecom India разместила на youtube видео о их новом дата-центре. Согласно информации от IBM этот крупнейший в Индии и третий по величине в мире дата-центр был построен за 9 месяцев. Это очень хороший показатель.&lt;br /&gt;
&lt;br /&gt;
- Общая площадь дата-центра 900,000 кв. м.&lt;br /&gt;
- Дизайн соответствует Tier-3 спецификации (TIA-942 стандарт) (*). &lt;br /&gt;
- Питание 66кВ с мощность 40 МВА со 100% резервированием&lt;br /&gt;
- Независимые внешние интерконнекты с различными интернет сервис провайдерам&lt;br /&gt;
- Изолированные помещения для установки серверов по 10,000 кв. м. на секцию&lt;br /&gt;
- Высокая энергоэффективность - PUE ~1.9 (**)&lt;br /&gt;
- 80,000 кв.м. выделено под офисные помещения&lt;br /&gt;
- Автоматизированная система управления зданием&lt;br /&gt;
&lt;a name='more'&gt;&lt;/a&gt;&lt;br /&gt;
&lt;iframe width="560" height="315" src="http://www.youtube.com/embed/-h5RYflgBcM" frameborder="0" allowfullscreen&gt;&lt;/iframe&gt;&lt;br /&gt;
&lt;br /&gt;
(*) Tier 3 (N+1) - возможность проведения ремонтно-восстановительных работ (включая замену компонентов системы, добавление и удаление вышедшего из строя оборудования) без прерывания работы дата-центра; подается несколько вводов электропитания; инженерные системы работают в режимы active/standby - системы электропитания и охлаждения дублированы, однако активна всегда только одна система &lt;a href="http://dcnt.ru/?p=22"&gt;Tier data center — уровни надежности дата-центра&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
(**) &lt;a href="http://searchdatacenter.techtarget.com/definition/power-usage-effectiveness-PUE"&gt;PUE, Power usage effectiveness&lt;/a&gt; - коэффициент, показывающий насколько эффективно используется энергия для вычислительных систем, по отношению к инфраструктуре дата-центра (системы кондиционирования, ...). &lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Ссылки:&lt;/b&gt;&lt;br /&gt;
&lt;a href="http://ru.wikipedia.org/wiki/%D0%94%D0%B0%D1%82%D0%B0-%D1%86%D0%B5%D0%BD%D1%82%D1%80"&gt;Дата-центр/Wikipedia&lt;/a&gt;&lt;br /&gt;
The Green Grid &lt;a href="http://www.thegreengrid.org/"&gt;http://www.thegreengrid.org/&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2025136836330523605-7108699313158369239?l=devel.ownport.net' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/develforfun/~4/_WlD4hFCkFM" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://devel.ownport.net/feeds/7108699313158369239/comments/default" title="Комментарии к сообщению" /><link rel="replies" type="text/html" href="http://devel.ownport.net/2012/02/tulip-telecom-india.html#comment-form" title="Комментарии: 0" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/2025136836330523605/posts/default/7108699313158369239?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/2025136836330523605/posts/default/7108699313158369239?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/develforfun/~3/_WlD4hFCkFM/tulip-telecom-india.html" title="Дата-центр Tulip Telecom India" /><author><name>d.rey</name><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://img.youtube.com/vi/-h5RYflgBcM/default.jpg" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://devel.ownport.net/2012/02/tulip-telecom-india.html</feedburner:origLink></entry><entry gd:etag="W/&quot;C0QMQHgzfyp7ImA9WhRaEUs.&quot;"><id>tag:blogger.com,1999:blog-2025136836330523605.post-7319973623634559823</id><published>2012-02-13T21:29:00.001+02:00</published><updated>2012-02-13T21:29:41.687+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-02-13T21:29:41.687+02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="free" /><category scheme="http://www.blogger.com/atom/ns#" term="science" /><category scheme="http://www.blogger.com/atom/ns#" term="computing" /><category scheme="http://www.blogger.com/atom/ns#" term="book" /><title>Книга "Introduction to Computing"</title><content type="html">&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/-xwKuEFTbe_k/Tzlh6eouHPI/AAAAAAAAAeg/zFCQMXnyhVM/s1600/Introduction%2Bto%2Bcomputing.jpg" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://3.bp.blogspot.com/-xwKuEFTbe_k/Tzlh6eouHPI/AAAAAAAAAeg/zFCQMXnyhVM/s1600/Introduction%2Bto%2Bcomputing.jpg" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;a href="http://www.cs.virginia.edu/~evans/"&gt;Девид Эванс (David Evans)&lt;/a&gt;, донент &lt;a href="http://www.virginia.edu/"&gt;Университета Вирджиния&lt;/a&gt; по вычислительным системам опубликовал в Интернет свою книгу - &lt;a href="http://www.computingbook.org/"&gt;Introduction to Computing. Explorations in Language, Logic, and Machines&lt;/a&gt;. В полном объеме книга доступна для скачивания в &lt;a href="http://www.computingbook.org/FullText.pdf"&gt;PDF формате&lt;/a&gt;, ее можно прочесть в &lt;a href="http://www.cs.virginia.edu/~evans/cs1120-f11/all/2011/on-line-version-of-course-book"&gt;онлайн&lt;/a&gt;, для любителей бумажных книг она доступна для заказа через &lt;a href="http://www.computingbook.org/printed.html"&gt;Amazon или CreateSpace&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;
Данная книга является вводной частью в вычислительные системы. Но может быть интерестна не только новичкам. Осноная идея книги показать различные информационные процессы через описания процедур. Какова цена реализации решения для различных подходов? Рассматриваются вопросы, что может быть расчитано, а что нет.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2025136836330523605-7319973623634559823?l=devel.ownport.net' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/develforfun/~4/vUoomdEiQWw" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://devel.ownport.net/feeds/7319973623634559823/comments/default" title="Комментарии к сообщению" /><link rel="replies" type="text/html" href="http://devel.ownport.net/2012/02/introduction-to-computing.html#comment-form" title="Комментарии: 0" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/2025136836330523605/posts/default/7319973623634559823?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/2025136836330523605/posts/default/7319973623634559823?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/develforfun/~3/vUoomdEiQWw/introduction-to-computing.html" title="Книга &quot;Introduction to Computing&quot;" /><author><name>d.rey</name><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://3.bp.blogspot.com/-xwKuEFTbe_k/Tzlh6eouHPI/AAAAAAAAAeg/zFCQMXnyhVM/s72-c/Introduction%2Bto%2Bcomputing.jpg" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://devel.ownport.net/2012/02/introduction-to-computing.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DUUEQH09fCp7ImA9WhRbFk0.&quot;"><id>tag:blogger.com,1999:blog-2025136836330523605.post-3573247311917845331</id><published>2012-02-07T07:20:00.000+02:00</published><updated>2012-02-07T11:33:21.364+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-02-07T11:33:21.364+02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="data" /><category scheme="http://www.blogger.com/atom/ns#" term="process" /><category scheme="http://www.blogger.com/atom/ns#" term="visualization" /><category scheme="http://www.blogger.com/atom/ns#" term="graphviz" /><category scheme="http://www.blogger.com/atom/ns#" term="flow" /><title>Визуализация данных с помощью graphviz</title><content type="html">&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/-aKq7dEwhsRw/TzC0R7ZhoJI/AAAAAAAAAeU/cbBRyjLKmmU/s1600/graphviz-cluster.png" imageanchor="1" style="clear:left; float:left;margin-right:1em; margin-bottom:1em"&gt;&lt;img border="0" height="241" width="125" src="http://3.bp.blogspot.com/-aKq7dEwhsRw/TzC0R7ZhoJI/AAAAAAAAAeU/cbBRyjLKmmU/s320/graphviz-cluster.png" /&gt;&lt;/a&gt;&lt;/div&gt;В многих случаях информация намного лучше воспринимается, когда она представлена графически. Для случаев построения сложных схем, графическое представление информации - необходимое условие. Кто-то для этого использует PowerPoint, кто-то Visio, кто-то Dia. Не очень удобным является подход поддержки в актуальном виде схем, созданных с помощью этих приложений - требуется постоянное вовлечение человека. И как часто это бывает схемы или диаграммы часто не отображают реальную картину состояния дел. Graphviz позволяет решить некоторые из этих вопросов.&lt;br /&gt;
&lt;br /&gt;
&lt;a href="http://www.graphviz.org/"&gt;Graphviz&lt;/a&gt; - это открытое программное обеспечения для построение графов. Принцип работы достаточно прост: подготавливается описание графа в текстовом виде, далее с помощью утилит graphviz граф может быть преобразован в различные форматы от текстового представления до PDF документов. В основном работа выполняется в командной строке, но на сайте, в разделе &lt;a href="http://www.graphviz.org/Resources.php"&gt;Ресурсы&lt;/a&gt; можно найти много GUI приложений как платных так и бесплатных. Там же можно найти примеры использования graphviz в различных отраслях и сферах: инжиниринг, био-информатика, описание интерфейсов, программы искусственного интеллекта.&lt;br /&gt;
&lt;a name='more'&gt;&lt;/a&gt;&lt;br /&gt;
Пример простого графа:&lt;br /&gt;
&lt;pre&gt;digraph g {
    "process1" -&amp;gt; "process2" -&amp;gt; "process3";
}&lt;/pre&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/-st9Bw-8AkxU/TzCxiRecQfI/AAAAAAAAAdw/KHGTtRLgC6g/s1600/graphviz-example1.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://4.bp.blogspot.com/-st9Bw-8AkxU/TzCxiRecQfI/AAAAAAAAAdw/KHGTtRLgC6g/s1600/graphviz-example1.png" /&gt;&lt;/a&gt;&lt;/div&gt;С помощью ключевых слов node и edge можно управлять глобальными параметрами формой фигур, цветом, шрифтами, формами стрелок. Например:&lt;br /&gt;
&lt;pre&gt;digraph g {
    rankdir=LR;
    node [fontsize=8,fontname="Verdana",style="rounded",];
    "input1" [shape="plaintext",label="input"];
    "output1" [shape="plaintext",label="ouput"];
    "process1" [shape="rectangle",label="Process 1"];
    "process2" [shape="rectangle",label="Process 2"];
    "input1" -&amp;gt; "process1";
    "process1" -&amp;gt; "process2";
    "process2" -&amp;gt; "output1";
}&lt;/pre&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/-0pQiNl_eTBs/TzCx_iKGa2I/AAAAAAAAAd8/0dJ00u1u_Ak/s1600/graphviz-example2.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://3.bp.blogspot.com/-0pQiNl_eTBs/TzCx_iKGa2I/AAAAAAAAAd8/0dJ00u1u_Ak/s1600/graphviz-example2.png" /&gt;&lt;/a&gt;&lt;/div&gt;Атрибут rankdir  позволяет изменить направление графа в LR (left-to-right). “node” определяет общие для всех нод параметры. Строка  &lt;br /&gt;
&lt;pre&gt;"input1" [shape="plaintext",label="input"];&lt;/pre&gt;определяет входные данные: “input1” - &lt;a href="http://www.graphviz.org/content/attrs#did"&gt;идентификатор ноды&lt;/a&gt;, &lt;a href="http://www.graphviz.org/content/node-shapes"&gt;shape&lt;/a&gt; определяет какая форма будет использована для отображения, label http://www.graphviz.org/content/attrs#dlabel указывает на информацию, отображаемую в теле ноды. Для связки нод между собой используется “-&amp;gt;” &lt;br /&gt;
&lt;br /&gt;
В версиях graphviz, начиная с середины ноября 2003 года текстовые метки label поддерживают HTML подобные теги. Это позволяет строить более информативные графы.&lt;br /&gt;
&lt;pre&gt;digraph g {
    rankdir=TB;
    node [fontsize=8,fontname="Verdana",shape="rectangle",style="rounded",];
    edge [fontsize=8,fontname="Verdana",color="grey20",];
    "input1" [penwidth=0.1,label=&amp;lt;&amp;lt;table border="0"&amp;gt;&amp;lt;tr&amp;gt;&amp;lt;td bgcolor="grey" align="center"&amp;gt;&amp;lt;font color="white"&amp;gt;Input&amp;lt;/font&amp;gt;&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;path&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&amp;lt;/table&amp;gt;&amp;gt;];
    "treewalker" [label=&amp;lt;&amp;lt;table border="0"&amp;gt;&amp;lt;tr&amp;gt;&amp;lt;td bgcolor="grey18" align="center"&amp;gt;&amp;lt;font color="white"&amp;gt;treewalker&amp;lt;/font&amp;gt;&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;core3.processes.treewalker3&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Scan files and directories&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&amp;lt;/table&amp;gt;&amp;gt;];
    "filehash" [label=&amp;lt;&amp;lt;table border="0"&amp;gt;&amp;lt;tr&amp;gt;&amp;lt;td bgcolor="grey18" align="center"&amp;gt;&amp;lt;font color="white"&amp;gt;filehash&amp;lt;/font&amp;gt;&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;core3.processes.filehash2&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Calculate MD5 hash sum&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&amp;lt;/table&amp;gt;&amp;gt;];
    "printer" [label=&amp;lt;&amp;lt;table border="0"&amp;gt;&amp;lt;tr&amp;gt;&amp;lt;td bgcolor="grey18" align="center"&amp;gt;&amp;lt;font color="white"&amp;gt;printer&amp;lt;/font&amp;gt;&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;__main__.printer&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Print out result on the screen&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&amp;lt;/table&amp;gt;&amp;gt;];

    "treewalker-filehash" [penwidth=0.1,label=&amp;lt;&amp;lt;table border="0"&amp;gt;&amp;lt;tr&amp;gt;&amp;lt;td bgcolor="grey" align="center"&amp;gt;&amp;lt;font color="white"&amp;gt;packet&amp;lt;/font&amp;gt;&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;path&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&amp;lt;/table&amp;gt;&amp;gt;];
    "filehash-printer" [penwidth=0.1,label=&amp;lt;&amp;lt;table border="0"&amp;gt;&amp;lt;tr&amp;gt;&amp;lt;td bgcolor="grey" align="center"&amp;gt;&amp;lt;font color="white"&amp;gt;packet&amp;lt;/font&amp;gt;&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;path&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;md5hashsum&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&amp;lt;/table&amp;gt;&amp;gt;];

    "input1" -&amp;gt; "treewalker" -&amp;gt; "treewalker-filehash" -&amp;gt; "filehash";
    "filehash" -&amp;gt; "filehash-printer" -&amp;gt; "printer";
}&lt;/pre&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/-6Av6mtZjH5s/TzCy96IouSI/AAAAAAAAAeI/gLCOfHZI7JU/s1600/graphviz-example3.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://2.bp.blogspot.com/-6Av6mtZjH5s/TzCy96IouSI/AAAAAAAAAeI/gLCOfHZI7JU/s1600/graphviz-example3.png" /&gt;&lt;/a&gt;&lt;/div&gt;Детальное описание по работе с graphviz можно найти по ссылкам ниже&lt;br /&gt;
&lt;br /&gt;
Graphviz - Graph Visualization Software &lt;a href="http://www.graphviz.org/"&gt;http://www.graphviz.org&lt;/a&gt;&lt;br /&gt;
Graphviz Node Shapes &lt;a href="http://www.graphviz.org/content/node-shapes"&gt;http://www.graphviz.org/content/node-shapes&lt;/a&gt;&lt;br /&gt;
Graphviz Color Names &lt;a href="http://www.graphviz.org/doc/info/colors.html"&gt;http://www.graphviz.org/doc/info/colors.html&lt;/a&gt;&lt;br /&gt;
Описание Graphviz на lib.custis.ru &lt;a href="http://lib.custis.ru/Graphviz"&gt;http://lib.custis.ru/Graphviz&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2025136836330523605-3573247311917845331?l=devel.ownport.net' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/develforfun/~4/StRUFGwklGY" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://devel.ownport.net/feeds/3573247311917845331/comments/default" title="Комментарии к сообщению" /><link rel="replies" type="text/html" href="http://devel.ownport.net/2012/02/graphviz.html#comment-form" title="Комментарии: 0" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/2025136836330523605/posts/default/3573247311917845331?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/2025136836330523605/posts/default/3573247311917845331?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/develforfun/~3/StRUFGwklGY/graphviz.html" title="Визуализация данных с помощью graphviz" /><author><name>d.rey</name><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://3.bp.blogspot.com/-aKq7dEwhsRw/TzC0R7ZhoJI/AAAAAAAAAeU/cbBRyjLKmmU/s72-c/graphviz-cluster.png" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://devel.ownport.net/2012/02/graphviz.html</feedburner:origLink></entry><entry gd:etag="W/&quot;A0AFQnk5fip7ImA9WhRbEkk.&quot;"><id>tag:blogger.com,1999:blog-2025136836330523605.post-3554267479909194344</id><published>2012-02-03T07:16:00.001+02:00</published><updated>2012-02-03T08:15:13.726+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-02-03T08:15:13.726+02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="structure" /><category scheme="http://www.blogger.com/atom/ns#" term="description" /><category scheme="http://www.blogger.com/atom/ns#" term="pyflowctrl" /><category scheme="http://www.blogger.com/atom/ns#" term="packet" /><category scheme="http://www.blogger.com/atom/ns#" term="json" /><category scheme="http://www.blogger.com/atom/ns#" term="scheme" /><title>Описание сложных типов данных для потоков</title><content type="html">&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/-iNa2Or0pcDU/TytsqaaNhaI/AAAAAAAAAdk/10uj1zskr6Y/s1600/atoms.jpg" imageanchor="1" style="clear:left; float:left;margin-right:1em; margin-bottom:1em"&gt;&lt;img border="0" height="90" width="120" src="http://4.bp.blogspot.com/-iNa2Or0pcDU/TytsqaaNhaI/AAAAAAAAAdk/10uj1zskr6Y/s320/atoms.jpg" /&gt;&lt;/a&gt;&lt;/div&gt;Потоки играют важную роль в обмене информации между процессами. Единицей переноса информации в потоках являются &lt;a href="http://devel.ownport.net/2012/01/pyflowctrl.html"&gt;пакеты&lt;/a&gt;. Описание структур пакетов позволяется без анализа кода процесса связывать процессы между собой. Простые структуры данных (без вложений) содержащиеся в пакетах можно описать достаточно просто. Для каждого параметра определить имя, тип и описание. Для случаев, когда данные переданные в потоках имеют сложную,  иерархическую структуру для их описания требуется определенный синтаксис.&lt;br /&gt;
&lt;a name='more'&gt;&lt;/a&gt;&lt;br /&gt;
Древовидные структуры данных в python удобно представлять в виде словарей (dictionary). Можно провести параллель структуры словаря python с JSON форматом. В обоих случаях для хранения данных используются схожие подходы. Для описания данных хранимых в JSON формате используется &lt;a href="http://tools.ietf.org/html/draft-zyp-json-schema-03"&gt;JSON Scheme&lt;/a&gt;. Принципы заложенные в этой спецификации можно использовать и для описания данных, хранимых в python словарях, а соответственно использовать для описания структуры данных пакетов &lt;a href="http://code.google.com/p/pyflowctrl/"&gt;pyflowctrl&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;
Кроме возможности корректной связи между собой процессов, описание должно иметь форму доступную для анализа не только человеком, но и программой. Это позволит выполнять валидацию данных передаваемых между процессами.&lt;br /&gt;
&lt;br /&gt;
Базовая спецификация JSON Schema определяет 8 типов данных JSON объекта: Object, Array, String, Number, Integer, Boolean, Null, Any. Два из них вложенные типы - Object и Array, 5 атомарных и один тип Any, который может содержать любые значения, включая Null. Для описания используются строки: “object”, “array”, “string”, “number”, “integerer”,”boolean”,”null”,”any”. Например:&lt;pre&gt;"module": {
    "type": "string",
    "title": "Module name",
     "required": "true",
    }&lt;/pre&gt;где атрибут type - описывает тип, title - краткое описание свойства объекта. Дополнительно к title можно указать атрибут description для более детального документирования свойтсва объекта. Атрибуты title и description - опциональны. По умолчанию принято, что все свойства в схеме опциональные. Если какое-то свойство должно быть  обязательно определено, оно должно быть описано с помощью атрибута required.&lt;br /&gt;
&lt;br /&gt;
Для описания структур, таких как массивы существует атрибут items, определяющий типы элементов в массиве.&lt;pre&gt;"based_on": {
    "type": "array",
        "title": "list of bassed-on classes",
        "items": {
            "type": "string",
            "title": "Based-on class",
        }
},&lt;/pre&gt;Для описания объектов используется атрибуты object и properties&lt;pre&gt;{
    "type": "object",
    "title": "Class of module",
    "properties:": {
        "name": {
            "type": "string",
            "title": "name of class",
            "required": "true",
        },
        "path": {
            "type": "string",
            "title": "path for class importing",
            "required": "true",
        },
}&lt;/pre&gt;Примеры, приведенные выше взяты из последней версии процесса &lt;a href="http://code.google.com/p/pyflowctrl/source/browse/pyflowctrl/core4/processes/pymetainfo2.py"&gt;PyMetaInfo&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Ссылки:&lt;/b&gt;&lt;br /&gt;
JSON Scheme &lt;a href="http://tools.ietf.org/html/draft-zyp-json-schema-03"&gt;http://tools.ietf.org/html/draft-zyp-json-schema-03&lt;/a&gt;&lt;br /&gt;
JSON validator &lt;a href="http://code.google.com/p/jsonvalidator/"&gt;http://code.google.com/p/jsonvalidator/&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
Логотип: &lt;a href="http://www.freedigitalphotos.net/images/view_photog.php?photogid=659"&gt;Salvatore Vuono / FreeDigitalPhotos.net&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2025136836330523605-3554267479909194344?l=devel.ownport.net' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/develforfun/~4/aKQh--plzyM" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://devel.ownport.net/feeds/3554267479909194344/comments/default" title="Комментарии к сообщению" /><link rel="replies" type="text/html" href="http://devel.ownport.net/2012/02/blog-post.html#comment-form" title="Комментарии: 0" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/2025136836330523605/posts/default/3554267479909194344?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/2025136836330523605/posts/default/3554267479909194344?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/develforfun/~3/aKQh--plzyM/blog-post.html" title="Описание сложных типов данных для потоков" /><author><name>d.rey</name><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://4.bp.blogspot.com/-iNa2Or0pcDU/TytsqaaNhaI/AAAAAAAAAdk/10uj1zskr6Y/s72-c/atoms.jpg" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://devel.ownport.net/2012/02/blog-post.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CUMEQHYycCp7ImA9WhRUGEw.&quot;"><id>tag:blogger.com,1999:blog-2025136836330523605.post-429184493348428618</id><published>2012-01-29T07:03:00.000+02:00</published><updated>2012-01-29T07:03:21.898+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-01-29T07:03:21.898+02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="free" /><category scheme="http://www.blogger.com/atom/ns#" term="mongodb" /><category scheme="http://www.blogger.com/atom/ns#" term="book" /><title>Небольшая книга о MongoDB</title><content type="html">&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://1.bp.blogspot.com/-MooC3V8Jqds/TyTRPeLN4PI/AAAAAAAAAdY/hBOqdIYOfic/s1600/the_little_mongodb_book.png" imageanchor="1" style="clear: left; display: inline !important; float: left; margin-bottom: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://1.bp.blogspot.com/-MooC3V8Jqds/TyTRPeLN4PI/AAAAAAAAAdY/hBOqdIYOfic/s1600/the_little_mongodb_book.png" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;i&gt;It's not my fault the chapters are short, MongoDB is just easy to learn.&lt;/i&gt;&lt;br /&gt;
&lt;br /&gt;
Эта книга была написана всего за 4-5 часов. Немного более 30 страниц. Описана только базовая функциональность MongoDB. Примеры приводятся для командной строки. Первое конфигурирование. Что такое NoSQL базы данных и их реализация в MongoDB. Как управлять данными: insert, find, update. Моделирование данных: no joins, массивы и встроенные документы, коллекции. Когда использовать MongoDB.&amp;nbsp;MapReduce. Производительность и инструменты&lt;br /&gt;
&lt;br /&gt;
Книга The Little MongoDB Book бесплатна и доступна на &lt;a href="http://openmymind.net/2011/3/28/The-Little-MongoDB-Book/"&gt;сайте автора&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2025136836330523605-429184493348428618?l=devel.ownport.net' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/develforfun/~4/0lsLr0rZImg" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://devel.ownport.net/feeds/429184493348428618/comments/default" title="Комментарии к сообщению" /><link rel="replies" type="text/html" href="http://devel.ownport.net/2012/01/mongodb.html#comment-form" title="Комментарии: 0" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/2025136836330523605/posts/default/429184493348428618?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/2025136836330523605/posts/default/429184493348428618?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/develforfun/~3/0lsLr0rZImg/mongodb.html" title="Небольшая книга о MongoDB" /><author><name>d.rey</name><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://1.bp.blogspot.com/-MooC3V8Jqds/TyTRPeLN4PI/AAAAAAAAAdY/hBOqdIYOfic/s72-c/the_little_mongodb_book.png" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://devel.ownport.net/2012/01/mongodb.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CkMGQXg6fip7ImA9WhRUFUs.&quot;"><id>tag:blogger.com,1999:blog-2025136836330523605.post-4404463027430968598</id><published>2012-01-26T08:47:00.000+02:00</published><updated>2012-01-26T08:47:00.616+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-01-26T08:47:00.616+02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="data" /><category scheme="http://www.blogger.com/atom/ns#" term="production" /><category scheme="http://www.blogger.com/atom/ns#" term="pyflowctrl" /><category scheme="http://www.blogger.com/atom/ns#" term="conveyor" /><category scheme="http://www.blogger.com/atom/ns#" term="processing" /><title>Другой взгляд на pyflowctrl</title><content type="html">Бывает так, что для того чтобы лучше понять как работает система, нужно привести примеры подобия с другими системами. Вчера, случайно наткнувшись на сайт компании &lt;a href="http://www.eagletechnologies.com/"&gt;Eagle Technologies&lt;/a&gt;, специализирующейся на системах автоматизации производств, понял, что работу &lt;a href="http://code.google.com/p/pyflowctrl/"&gt;pyflowctrl&lt;/a&gt; можно сравнить с &lt;a href="http://ru.wikipedia.org/wiki/%D0%9F%D0%BE%D1%82%D0%BE%D1%87%D0%BD%D0%BE%D0%B5_%D0%BF%D1%80%D0%BE%D0%B8%D0%B7%D0%B2%D0%BE%D0%B4%D1%81%D1%82%D0%B2%D0%BE"&gt;поточным производством&lt;/a&gt;. Где в качестве как сырья, так и конечного изделия выступают данные. &lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/-gA30HmlfEO8/TyD123GT9MI/AAAAAAAAAdM/r60fxALyUl0/s1600/eagle-technologies-conveyor.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://1.bp.blogspot.com/-gA30HmlfEO8/TyD123GT9MI/AAAAAAAAAdM/r60fxALyUl0/s1600/eagle-technologies-conveyor.jpg" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;a name='more'&gt;&lt;/a&gt;&lt;br /&gt;
На вход системы поступают “сырые” данные (Packet), требующие обработки. Проходя каждый процесс (Process) обработки, согласно определенной логики (ProcessFlow) над данными выполняются ряд манипуляций по обработке. Связь между процессами осуществляется с помощью потоков (Stream). Именно они служат конвейером, средством транспортировки данных (Packet)  между процессами (Process). Точно также машина проходя по сборочному цеху преобразуется из простых металлоконструкций в законченное изделие.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2025136836330523605-4404463027430968598?l=devel.ownport.net' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/develforfun/~4/r-W0qCEo_Cg" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://devel.ownport.net/feeds/4404463027430968598/comments/default" title="Комментарии к сообщению" /><link rel="replies" type="text/html" href="http://devel.ownport.net/2012/01/pyflowctrl_26.html#comment-form" title="Комментарии: 0" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/2025136836330523605/posts/default/4404463027430968598?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/2025136836330523605/posts/default/4404463027430968598?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/develforfun/~3/r-W0qCEo_Cg/pyflowctrl_26.html" title="Другой взгляд на pyflowctrl" /><author><name>d.rey</name><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://1.bp.blogspot.com/-gA30HmlfEO8/TyD123GT9MI/AAAAAAAAAdM/r60fxALyUl0/s72-c/eagle-technologies-conveyor.jpg" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://devel.ownport.net/2012/01/pyflowctrl_26.html</feedburner:origLink></entry><entry gd:etag="W/&quot;C0cDR3w5eyp7ImA9WhRUFEo.&quot;"><id>tag:blogger.com,1999:blog-2025136836330523605.post-9104823231701983726</id><published>2012-01-25T07:57:00.002+02:00</published><updated>2012-01-25T07:57:56.223+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-01-25T07:57:56.223+02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="process" /><category scheme="http://www.blogger.com/atom/ns#" term="description" /><category scheme="http://www.blogger.com/atom/ns#" term="pyflowctrl" /><category scheme="http://www.blogger.com/atom/ns#" term="metadata" /><title>Описание процесса pyflowctrl</title><content type="html">Реализация процесса (класс Process) в pyflowctrl не позволяет определить с помощью &lt;a href="http://code.google.com/p/pyflowctrl/source/browse/pyflowctrl/core4/processes/pymetainfo1.py"&gt;pymetainfo&lt;/a&gt; достаточную информацию о процессе, без дополнительного его описания. Получаемые метаданные избыточны и содержат специфичную для python внутреннюю реализацию. Пример вывода можно посмотреть в посте “&lt;a href="http://devel.ownport.net/2012/01/c-python.html"&gt;Исследования python-кода&lt;/a&gt;”. &lt;br /&gt;
&lt;a name='more'&gt;&lt;/a&gt;&lt;br /&gt;
После анализа процессов предыдущих релизов pyflowctrl был сформирован черновой список, необходимой информации о процессе:&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;название процесса&lt;/li&gt;
&lt;li&gt;краткое описание процесса&lt;/li&gt;
&lt;li&gt;автор (-ы) кода процесса&lt;/li&gt;
&lt;li&gt;ссылки, где код процесса можно скачать&lt;/li&gt;
&lt;li&gt;зависимости с другими python модулями, библиотеками&lt;/li&gt;
&lt;li&gt;список потоков (входных, выходных, отладки)&lt;/li&gt;
&lt;li&gt;список функций с описанием&lt;/li&gt;
&lt;/ul&gt;Если определять перечисленные выше свойства в конструкторе процесса, получение информации о них, будет возможно только после создании экземпляра класса Process. В связи с тем, что метаданные о процессе часто являются статичными переменными, их можно вынести как атрибут процесса&lt;pre&gt;class Process(object):
    ''' Process '''
    
    __PROCESS__ = {
                    'name': 'Process',
                    'description': 'Basic process',
                    'author': '',
                    'url': '',
                    'depends on': '',
                    'io': {},
                }&lt;/pre&gt;Атрибут __PROCESS__ содержит словарь метаданных процесса, на основании которого базовый конструктор процесса выполняет создание экземпляра процесса. Наиболее важным является ключ “io”, определяющий словарь параметров потоков ввода/вывода. Пример __PROCESS__ на базе &lt;a href="http://code.google.com/p/pyflowctrl/source/browse/pyflowctrl/core4/processes/pymetainfo2.py"&gt;pymetainfo2.py&lt;/a&gt;:&lt;pre&gt;__PROCESS__ = {
                    'name': 'PyMetaInfo',
                    'description': 'Extact metadata information about module/class. Customized for pyflowctrl.',
                    'author': 'Andrey Usov &amp;lt;http://devel.ownport.net&amp;gt;',
                    'url': 'http://pyflowctrl.googlecode.com/hg/pyflowctrl/core4/processes/pymetainfo2.py',
                    'io': {'input': {}, 'output': {}, },
                }&lt;/pre&gt;Сейчас, если запустить pymetainfo2.py и указать в качестве аргумента его собственный код, вывод будет иметь следующий вид:&lt;pre&gt;$python examples/pymetainfo2.py pyflowctrl.core4.processes.pymetainfo2.PyMetaInfo

{'__namespaces': {},
 'meta': {'based_on': (&amp;lt;class 'pyflowctrl.core4.Process'&amp;gt;,),
          'classes': [('__class__', &amp;lt;type 'type'&amp;gt;, &amp;lt;type 'object'&amp;gt;)],
          'data': [('__PROCESS__',
                    {'author': 'Andrey Usov &amp;lt;http://devel.ownport.net&amp;gt;',
                     'description': 'Extact metadata information about module/class. Customized for pyflowctrl.',
                     'io': {'input': {}, 'output': {}},
                     'name': 'PyMetaInfo',
                     'url': 'http://pyflowctrl.googlecode.com/hg/pyflowctrl/core4/processes/pymetainfo1.py'})],
          'description': 'Extact metadata information about module/class ',
          'funcs': [('__init__', None),
                    ('get_classes', 'return list of classes '),
                    ('get_data', 'return data for object. filtered'),
                    ('get_elements',
                     "get list of object's elements by type"),
                    ('get_funcs', 'return list of functions, filtered'),
                    ('get_metadata', "get dictionary of object's metadata "),
                    ('get_modpkgs', "return list of module's packages "),
                    ('main', None),
                    ('remove_empty_meta', 'remove empty data '),
                    ('run_once',
                     'wrapper for main loop \n\nif packet is specified run_once return the result of processing\nif packet is not specified run_once return the status of process')],
          'name': 'PyMetaInfo',
          'type': &amp;lt;type 'type'&amp;gt;},
 'module': 'pyflowctrl.core4.processes.pymetainfo2.PyMetaInfo'}&lt;/pre&gt;Следует отметить, что с переходом на новый способ определения потоков ввода/вывода, возвращен, определенный в core3, подход доступа к потокам ввода/вывода.  &lt;br /&gt;
&lt;br /&gt;
получение пакета из входного потока &lt;i&gt;packet = process1.io['input'].get()&lt;/i&gt;&lt;br /&gt;
&lt;br /&gt;
запись пакета в поток вывода &lt;i&gt;process1.io['output'].put(packet)&lt;/i&gt;&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2025136836330523605-9104823231701983726?l=devel.ownport.net' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/develforfun/~4/xNwyKoRbqqI" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://devel.ownport.net/feeds/9104823231701983726/comments/default" title="Комментарии к сообщению" /><link rel="replies" type="text/html" href="http://devel.ownport.net/2012/01/pyflowctrl_25.html#comment-form" title="Комментарии: 0" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/2025136836330523605/posts/default/9104823231701983726?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/2025136836330523605/posts/default/9104823231701983726?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/develforfun/~3/xNwyKoRbqqI/pyflowctrl_25.html" title="Описание процесса pyflowctrl" /><author><name>d.rey</name><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>0</thr:total><feedburner:origLink>http://devel.ownport.net/2012/01/pyflowctrl_25.html</feedburner:origLink></entry><entry gd:etag="W/&quot;Ak8FRnYzeCp7ImA9WhRVGEs.&quot;"><id>tag:blogger.com,1999:blog-2025136836330523605.post-2982962409464220453</id><published>2012-01-12T08:20:00.001+02:00</published><updated>2012-01-18T08:40:17.880+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-01-18T08:40:17.880+02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="pyflowctrl" /><category scheme="http://www.blogger.com/atom/ns#" term="python" /><category scheme="http://www.blogger.com/atom/ns#" term="code" /><category scheme="http://www.blogger.com/atom/ns#" term="introspection" /><title>Иcследование python кода</title><content type="html">&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://3.bp.blogspot.com/-7rMaD5c1Yps/Tw57Ih_sIsI/AAAAAAAAAc4/AQs8sygMPlE/s1600/magnifying_glass.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="90" src="http://3.bp.blogspot.com/-7rMaD5c1Yps/Tw57Ih_sIsI/AAAAAAAAAc4/AQs8sygMPlE/s320/magnifying_glass.png" width="120" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;a href="http://ru.wikipedia.org/wiki/%D0%98%D0%BD%D1%82%D1%80%D0%BE%D1%81%D0%BF%D0%B5%D0%BA%D1%86%D0%B8%D1%8F_(%D0%BF%D1%80%D0%BE%D0%B3%D1%80%D0%B0%D0%BC%D0%BC%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5)"&gt;Интроспекция&lt;/a&gt;(англ. type introspection) в программировании — возможность в некоторых объектно-ориентированных языках определить тип и структуру объекта во время выполнения программы. &lt;a href="http://ru.wikipedia.org/"&gt;Wikipedia&lt;/a&gt;. Для python эта возможность интегрирована в сам язык. Хороший пример интроспекции в python - встроенная система помощи. Для любого кода на python достаточно набрать в командной строке: &lt;br /&gt;
&lt;pre&gt;$ pydoc "module/class/function name"&lt;/pre&gt;
как результат будет получено описание по модулю, классу или функции (см. примечание к посту ниже). &lt;br /&gt;
&lt;a name='more'&gt;&lt;/a&gt;&lt;br /&gt;
Наибольший интерес представляет возможность анализа программы другой программой. В рамках проекта &lt;a href="http://code.google.com/p/pyflowctrl/"&gt;pyflowctrl&lt;/a&gt; это может быть очень полезной функциональностью, когда менеджер процессов ProcessFlow получает информации о процессах и осуществляет соединение на основании характеристик входных/выходных потоков. &lt;br /&gt;
&lt;br /&gt;
Процесс &lt;a href="http://pyflowctrl.googlecode.com/hg/pyflowctrl/core4/processes/pymetainfo1.py"&gt;PyMetaInfo&lt;/a&gt; позволяет провести анализ кода переданного имени модуля и вернуть метаданные в виде словаря. Пример использования процесса приведен в коде &lt;a href="http://code.google.com/p/pyflowctrl/source/browse/pyflowctrl/core4/examples/pymetainfo1.py"&gt;examples/pymetainfo1.py&lt;/a&gt;. На вход процесса передается пакет, содержащий имя модуля packet.module:&lt;br /&gt;
&lt;pre&gt;$ python examples/pymetainfo1.py pyflowctrl
{'__namespaces': {},
 'meta': {'data': [('__author__', 'Andrey Usov &lt;http: devel.ownport.net=""&gt;')],
          'description': 'Python Flow Control Library ',
          'module_packages': ['core4 (package)',
                              'examples (package)',
                              'libs (package)',
                              'processes (package)',
                              'streams (package)'],
          'name': 'pyflowctrl',
          'submodules': [('core4',
                          &lt;module '="" 'pyflowctrl.core4'="" __init__.pyc'="" core4="" data="" devel="" from="" media="" pyflowctrl=""&gt;)],
          'type': &lt;type 'module'=""&gt;},
 'module': 'pyflowctrl'}&lt;/type&gt;&lt;/module&gt;&lt;/http:&gt;&lt;/pre&gt;
На выходе получаем пакет с метаданными о библиотете. Пример вывода информации о процессе:  &lt;br /&gt;
&lt;pre&gt;$ python examples/pymetainfo1.py pyflowctrl.core4.processes.pymetainfo1.PyMetaInfo
{'__namespaces': {},
 'meta': {'based_on': (&lt;class 'pyflowctrl.core4.process'=""&gt;,),
          'classes': [('__class__', &lt;type 'type'=""&gt;, &lt;type 'object'=""&gt;)],
          'data': [('__dict__',
                    dict_proxy({'__module__': 'pyflowctrl.core4.processes.pymetainfo1', 'get_elements': &lt;function 0x2a21b18="" at="" get_elements=""&gt;, 'get_classes': &lt;function 0x2a21b90="" at="" get_classes=""&gt;, 'get_modpkgs': &lt;function 0x2a21c08="" at="" get_modpkgs=""&gt;, 'get_metadata': &lt;function 0x2a21c80="" at="" get_metadata=""&gt;, 'main': &lt;function 0x2a21cf8="" at="" main=""&gt;, '__doc__': ' Extact metadata information about module/class ', '__init__': &lt;function 0x29ba938="" __init__="" at=""&gt;})),
                   ('__weakref__',
                    &lt;attribute '__weakref__'="" 'process'="" objects="" of=""&gt;)],
          'description': 'Extact metadata information about module/class ',
          'funcs': [('__delattr__',
                     &lt;slot '__delattr__'="" 'object'="" objects="" of="" wrapper=""&gt;),
      
                    . . .

                    ('get_classes', &lt;unbound method="" pymetainfo.get_classes=""&gt;),
                    ('get_elements',
                     &lt;unbound method="" pymetainfo.get_elements=""&gt;),
                    ('get_metadata',
                     &lt;unbound method="" pymetainfo.get_metadata=""&gt;),
                    ('get_modpkgs', &lt;unbound method="" pymetainfo.get_modpkgs=""&gt;),
                    ('main', &lt;unbound method="" pymetainfo.main=""&gt;),
                    ('run_once', &lt;unbound method="" pymetainfo.run_once=""&gt;)],
          'name': 'PyMetaInfo',
          'type': &lt;type 'type'=""&gt;},
 'module': 'pyflowctrl.core4.processes.pymetainfo1.PyMetaInfo'}&lt;/type&gt;&lt;/unbound&gt;&lt;/unbound&gt;&lt;/unbound&gt;&lt;/unbound&gt;&lt;/unbound&gt;&lt;/unbound&gt;&lt;/slot&gt;&lt;/attribute&gt;&lt;/function&gt;&lt;/function&gt;&lt;/function&gt;&lt;/function&gt;&lt;/function&gt;&lt;/function&gt;&lt;/type&gt;&lt;/type&gt;&lt;/class&gt;&lt;/pre&gt;
Информация в выводе достаточно избыточна для работы pyflowctrl, отсутствует информация о потоках. Так как потоки создаются в __init__(), провести анализ содержимого объекта без его создания не получится. Необходимо пересмотреть принципы создания процессов для того, что бы существовала возможность получения информации о потоках без создания самого процесса.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Примечание&lt;/b&gt;: документация в python формируется автоматически на основании анализа кода объекта. При вызове pydoc выполняет импорт кода и проводит анализ его структуры, извлекает документацию.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2025136836330523605-2982962409464220453?l=devel.ownport.net' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/develforfun/~4/xtDg7eQvb7I" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://devel.ownport.net/feeds/2982962409464220453/comments/default" title="Комментарии к сообщению" /><link rel="replies" type="text/html" href="http://devel.ownport.net/2012/01/c-python.html#comment-form" title="Комментарии: 0" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/2025136836330523605/posts/default/2982962409464220453?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/2025136836330523605/posts/default/2982962409464220453?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/develforfun/~3/xtDg7eQvb7I/c-python.html" title="Иcследование python кода" /><author><name>d.rey</name><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://3.bp.blogspot.com/-7rMaD5c1Yps/Tw57Ih_sIsI/AAAAAAAAAc4/AQs8sygMPlE/s72-c/magnifying_glass.png" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://devel.ownport.net/2012/01/c-python.html</feedburner:origLink></entry><entry gd:etag="W/&quot;A08MSXk4eCp7ImA9WhRVEE0.&quot;"><id>tag:blogger.com,1999:blog-2025136836330523605.post-3590401168243368912</id><published>2012-01-08T07:03:00.000+02:00</published><updated>2012-01-08T10:04:48.730+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-01-08T10:04:48.730+02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="core" /><category scheme="http://www.blogger.com/atom/ns#" term="pyflowctrl" /><category scheme="http://www.blogger.com/atom/ns#" term="python" /><title>Новое ядро (сore4) для pyflowctrl</title><content type="html">&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/-0QlSKhlazYs/Td0QmxZusbI/AAAAAAAAAVE/POLgNtONbkQ/s1600/waterfall_process_flow.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://4.bp.blogspot.com/-0QlSKhlazYs/Td0QmxZusbI/AAAAAAAAAVE/POLgNtONbkQ/s1600/waterfall_process_flow.png" /&gt;&lt;/a&gt;&lt;/div&gt;Причины перехода на новое ядро в основном были описаны в предыдущем посте “&lt;a href="http://devel.ownport.net/2012/01/pyflowctrl.html"&gt;Информационные пакеты в pyflowctrl&lt;/a&gt;”. Предыдущее ядро работу с пакетами не поддерживало, а плавно перейти на их поддержку не получалось. Кроме этого переход на новое ядро был обусловлен еще и давним желанием вывести работу над pyflowctrl в отдельный проект. Сейчас проект размещен на &lt;a href="http://code.google.com/p/pyflowctrl/"&gt;code.google.com&lt;/a&gt;. &lt;br /&gt;
&lt;a name='more'&gt;&lt;/a&gt;&lt;br /&gt;
В будущем на нем будут публиковаться изменения начиная с ветки core4. С переходом на новую версию изменена структура директорий проекта:&lt;br /&gt;
&lt;br /&gt;
- core4.py перенесен в директорию core4 и__init__.py &lt;br /&gt;
- в директорию core4 добавлены под-директории processes/ для хранения кода процессов, streams/ для потоков, tests/ для тестов, examples/ для примеров работы с библиотекой, libs/ для хранения сторонних библиотек.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Изменения в логике работы core4 от core3 (core4 базируется на core3&lt;/b&gt;):&lt;br /&gt;
&lt;br /&gt;
В классе Process изменены атрибуты доступа к входным/выходным потокам. Сейчас доступ к ним осуществляется с помощью атрибутов input/output, которые нужно явно описать для нового процесса &lt;pre&gt;class TestProcess(Process):
    def __init__(self):
        super(TestProcess, self).__init__()
        self.input = Stream()
        self.output = Stream()&lt;/pre&gt;Пример определения основной функции процесса&lt;pre&gt;def main(self):
    while True:
        try:
            packet = self.input.get()
        except EmptyStream:
            yield WAITING
            continue
        # основной код для работы с данными пакета 
        self.output.put(packet)
        yield PROCESSING&lt;/pre&gt;В классе Stream убрана поддержка описания типизации потоков. В core3 давать описание потоков было не обязательно и зачастую потоки в процессах так и оставались без описаний, так как типизация данных приводила к сложностям соединения процессов. В будущем механизм описания данных в потоках будет доработан. В текущем релизе - это открытый вопрос.&lt;br /&gt;
&lt;br /&gt;
Основной единицей переноса данных между процессами является информационный пакет, класс Packet, см. “&lt;a href="http://devel.ownport.net/2012/01/pyflowctrl.html"&gt;Информационные пакеты в pyflowctrl&lt;/a&gt;”&lt;br /&gt;
&lt;br /&gt;
При создании пакета можно передавать “корневые ” переменные, которые он будет содержать &lt;pre&gt;&gt;&gt;&gt; p = Packet(counter=10, name=’test_process’)
&gt;&gt;&gt; p.counter, p.name
10 test_process&lt;/pre&gt;В классе ProcessFlow упрощен механизм создания сети взаимодействия процессов - словарь с описанием:&lt;pre&gt;network = {
    'processes': {
        'process1': TestProcess(),
        'process2': TestProcess(),
        'printer': Printer(),
    },
    'links': {
        # соединение между process1 и process2
        ('process1.output', 'process2.input', p1p2_handler), 
        # соединение между process2 и printer
        ('process2.output', 'printer.input', p2prn_handler),
    }
}&lt;/pre&gt;network[‘processes’] описывает процессы, участвующие в работе. Доступ к процессам осуществляется по их именам. &lt;br /&gt;
&lt;br /&gt;
network[‘links’] описывает взаимодействие между процессами. Каждое соединение - это список из трех аргументов: источник данных, получатель данных, обработчик данных. Источник и получатель данных  - это символьное описание, состоящее из имени процесса и имени потока. Обработчик данных позволяем изменить структуру пакета на этапе передачи его от процесса-источника до процесса-получателя. Это дает возможность адаптировать структуру пакета под нужды следующего процесса. Обработчик данных - это функция на вход которой поступает пакет и на выходе она должна возвращать его же, пример:&lt;pre&gt;def p1p2_handler(packet):
    # process1 -&gt; process2
    packet.set_namespace('test-env1')
    packet['test-env1'].name = packet.name
    packet['test-env1'].url = packet.url
    del packet.name
    del packet.url
    return packet&lt;/pre&gt;Если данные в обработке не нуждаются, то вместо обработчика данных передается None. &lt;pre&gt;'links': {
        ('process1.output', 'process2.input', None),
}&lt;/pre&gt;Обработчики данных можно использовать также как функции-отладчики для вывода данных обменивающихся между процессами.&lt;pre&gt;'links': {
        ('process1.output', 'process2.input', p1p2debug),
}&lt;/pre&gt;Загрузка сети network в ProcessFlow выполняется с помощью метода upload(network)&lt;pre&gt;flow = ProcessFlow()
flow.upload(network)
for i in xrange(10):
    flow.pmap['process1'].input.put(Packet(counter=i))
flow.run()&lt;/pre&gt;Метод run() выполняет запуск сети в работу&lt;br /&gt;
&lt;br /&gt;
Пример работы с core4 расположен в &lt;a href="http://pyflowctrl.googlecode.com/hg/core4/examples/example1.py"&gt;директории examples репозитория&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2025136836330523605-3590401168243368912?l=devel.ownport.net' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/develforfun/~4/QpKZUXPxo1o" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://devel.ownport.net/feeds/3590401168243368912/comments/default" title="Комментарии к сообщению" /><link rel="replies" type="text/html" href="http://devel.ownport.net/2012/01/ore4-pyflowctrl.html#comment-form" title="Комментарии: 0" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/2025136836330523605/posts/default/3590401168243368912?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/2025136836330523605/posts/default/3590401168243368912?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/develforfun/~3/QpKZUXPxo1o/ore4-pyflowctrl.html" title="Новое ядро (сore4) для pyflowctrl" /><author><name>d.rey</name><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://4.bp.blogspot.com/-0QlSKhlazYs/Td0QmxZusbI/AAAAAAAAAVE/POLgNtONbkQ/s72-c/waterfall_process_flow.png" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://devel.ownport.net/2012/01/ore4-pyflowctrl.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CUQAR346cSp7ImA9WhRWGUw.&quot;"><id>tag:blogger.com,1999:blog-2025136836330523605.post-3333478330547940426</id><published>2012-01-07T07:15:00.000+02:00</published><updated>2012-01-07T07:15:46.019+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-01-07T07:15:46.019+02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="process" /><category scheme="http://www.blogger.com/atom/ns#" term="control" /><category scheme="http://www.blogger.com/atom/ns#" term="pyflowctrl" /><category scheme="http://www.blogger.com/atom/ns#" term="python" /><category scheme="http://www.blogger.com/atom/ns#" term="packet" /><title>Информационные пакеты в pyflowctrl</title><content type="html">&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://4.bp.blogspot.com/-0QlSKhlazYs/Td0QmxZusbI/AAAAAAAAAVE/POLgNtONbkQ/s1600/waterfall_process_flow.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://4.bp.blogspot.com/-0QlSKhlazYs/Td0QmxZusbI/AAAAAAAAAVE/POLgNtONbkQ/s1600/waterfall_process_flow.png" /&gt;&lt;/a&gt;&lt;/div&gt;
Основой любой вычислительной системы является обработка информации: получение одних данных из других с пользованием некоторых алгоритмов. Долгое время основной акцент при разработке pyflowctrl делался на работе самих процессов. Когда каждый процесс рассматривается как черный ящик, со временем возникают сложности в организации их совместной работы. Отсутствие механизма согласованного обмена данных не только между двумя процессами, но и между процессами системы в целом, приводит к необходимости постоянно адаптировать существующие процессы под меняющиеся задачи и как следствие гибкость системы теряется.&lt;br /&gt;
&lt;a name='more'&gt;&lt;/a&gt;&lt;br /&gt;
Приведу пример диаграммы взаимодействия процессов одного из предыдущих постов - “&lt;a href="http://devel.ownport.net/2011/06/html.html"&gt;Извлекаем ссылки из HTML страницы&lt;/a&gt;”&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://4.bp.blogspot.com/-r8z6wRAmZMM/Tgf1G6NPxmI/AAAAAAAAAX4/1PFCJbrlmkc/s1600/UrlExtract.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://4.bp.blogspot.com/-r8z6wRAmZMM/Tgf1G6NPxmI/AAAAAAAAAX4/1PFCJbrlmkc/s1600/UrlExtract.png" /&gt;&lt;/a&gt;&lt;/div&gt;
Ранее на диаграммах отображались только сами процессы, обмен данных между процессами уходил на второй план. В примере выше, цепочка процессов могла работать только в такой конфигурации. Каждый процесс выдавал свой набор выходных данных и следующий за ним процесс мог работать только с этими данными. Если бы понадобилось использовать существующие процессы для других случаев, перед передачей данных в процесс их необходимо было специально обрабатывать, подстраивать под исходные параметры входного потока процесса. Конечно же, если исходить из того, что каждый процесс - это черный ящик, то от этого не уйти. Чаще всего процессы выполняют узконаправленную работу и работают с определенными типами входных и выходных данных.&lt;br /&gt;
&lt;br /&gt;
Больше сложностей создает отсутствие прозрачного пропуска через процесс данных, необходимые не в текущем процессе, но в последующих. Например: на вход системы подается документ, проходя через различные процессы документ изменяет свою структуру. Каждый процесс выполняет над документом только определенные манипуляции, тогда как в конце обработки, необходимо вывести все обработанные данные документа. При существующем подходе pyflowctrl.core3 приходится адаптировать существующие процессы под каждую конкретную задачу. Для того, чтобы избежать подобной необходимости в pyflowctrl.core4 вводится новое понятие - информационный пакет.&lt;br /&gt;
&lt;br /&gt;
Информационный пакет является контейнером, переносчиком данных между процессами. Структура пакета не статична, она может меняться, подстраиваться под конкретные нужды как каждого процесса, так системы обработки данных в целом. &lt;br /&gt;
&lt;pre&gt;from pyflowctrl.core4 import Packet

p = Packet()
# “корневая” область
p.id = 1
p.url = 'http://example.com'
p.content = '&amp;lt;html&amp;gt;&amp;lt;body&amp;gt;test 1&amp;lt;/body&amp;gt;&amp;lt;/html&amp;gt;'
p.tags = ['html','body']&lt;/pre&gt;
Процесс, получив пакет работает с его “корневыми” данными: принимает, обрабатывает, изменяют значения в существующих полях или создает новые. Важным моментом при таком подходе является необходимость избежания коллизии имен полей, используемых другими процессами и текущим процессом. Для решения этого вопроса в пакете можно создавать различные пространства имен (namespaces). Перед передачей пакета в процесс, данные, не относящиеся к текущему процессу переносятся из “корневой” области видимости в отдельное пространство имен. &lt;br /&gt;
&lt;pre&gt;# область имен “test-namespace”
p.set_namespace(“test-namespace”)
p[“test-namespace”].id = 10
p[“test-namespace”].url = 'http://example2.com'
p[“test-namespace”].content = '&amp;lt;html&amp;gt;&amp;lt;body&amp;gt;test 2&amp;lt;/body&amp;gt;&amp;lt;/html&amp;gt;'
p[“test-namespace”].tags = ['html','body']&lt;/pre&gt;
Размещая данные в различных пространствах имен можно прозрачно передавать данные, необходимые для следующего процесса.&lt;br /&gt;
&lt;br /&gt;
Пространства имен в пакете можно создавать с помощью метода &lt;i&gt;set_namespace(name)&lt;/i&gt;, удалять &lt;i&gt;del_namespace(name)&lt;/i&gt;, выводить список &lt;i&gt;namespaces()&lt;/i&gt;. &lt;br /&gt;
&lt;br /&gt;
В связи с тем, что пространства имен могут быть доступны внутри процесса существует риск нарушении структуры пакета самим процессом в случае ошибки или его некорректной работы. Процесс должен работать только с корневыми переменными, а управление данными в пространствах имен выполняется на уровне управления потоками процессов. Число пространств имен внутри пакета не ограничивается.&lt;br /&gt;
&lt;br /&gt;
Часто возникают ситуации, когда процесс при получении одного пакета, должен вернуть несколько. В этом случае, для сохранения данных из пространств имен  входного пакета, процесс должен скопировать &lt;i&gt;copy()&lt;/i&gt; исходный пакет и изменить в нем “корневые” поля.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2025136836330523605-3333478330547940426?l=devel.ownport.net' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/develforfun/~4/GqphAn3YKvw" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://devel.ownport.net/feeds/3333478330547940426/comments/default" title="Комментарии к сообщению" /><link rel="replies" type="text/html" href="http://devel.ownport.net/2012/01/pyflowctrl.html#comment-form" title="Комментарии: 0" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/2025136836330523605/posts/default/3333478330547940426?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/2025136836330523605/posts/default/3333478330547940426?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/develforfun/~3/GqphAn3YKvw/pyflowctrl.html" title="Информационные пакеты в pyflowctrl" /><author><name>d.rey</name><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://4.bp.blogspot.com/-0QlSKhlazYs/Td0QmxZusbI/AAAAAAAAAVE/POLgNtONbkQ/s72-c/waterfall_process_flow.png" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://devel.ownport.net/2012/01/pyflowctrl.html</feedburner:origLink></entry><entry gd:etag="W/&quot;AkQHRn4_cCp7ImA9WhRXE0g.&quot;"><id>tag:blogger.com,1999:blog-2025136836330523605.post-9129425462683115556</id><published>2011-12-20T07:18:00.001+02:00</published><updated>2011-12-20T07:18:57.048+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-12-20T07:18:57.048+02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="machine" /><category scheme="http://www.blogger.com/atom/ns#" term="stanford" /><category scheme="http://www.blogger.com/atom/ns#" term="online" /><category scheme="http://www.blogger.com/atom/ns#" term="free" /><category scheme="http://www.blogger.com/atom/ns#" term="course" /><category scheme="http://www.blogger.com/atom/ns#" term="learning" /><title>Курс "Машинное обучение", впечатления</title><content type="html">&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/--plt9AbvrJo/Togs-7fb1hI/AAAAAAAAAbE/vtjk9PqI9jM/s1600/machine_learning.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://2.bp.blogspot.com/--plt9AbvrJo/Togs-7fb1hI/AAAAAAAAAbE/vtjk9PqI9jM/s1600/machine_learning.png" /&gt;&lt;/a&gt;&lt;/div&gt;На прошлой неделе закончился курс &lt;a href="http://www.ml-class.org/"&gt;“Машинное обучение”&lt;/a&gt;. О нем я уже писал &lt;a href="http://devel.ownport.net/2011/10/blog-post.html"&gt;несколько месяцев назад&lt;/a&gt;, но напомню, это бесплатный online курс подготовленный профессором стенфордского университета &lt;a href="http://ai.stanford.edu/~ang/"&gt;Эндрю Энджи/Andrew Ng&lt;/a&gt; и его командой. Кратко темы курса:&lt;br /&gt;
&lt;br /&gt;
- Supervised learning: linear regression, logistic regression, neural networks, SVMs&lt;br /&gt;
- Unsupervised learning: K-means, PCA, Anomaly detection&lt;br /&gt;
- Special applications/special tools:&amp;nbsp;Recommended&amp;nbsp;systems, large scale machine&amp;nbsp;leanings&lt;br /&gt;
- Advice on building a machine learning system: bias/variance, regularization; deciding what to work in next: evaluation of learning algorithms, learning curves, error analysis, ceiling analysis.&lt;br /&gt;
&lt;a name='more'&gt;&lt;/a&gt;&lt;br /&gt;
Курс состоял их трех секций: лекции, теоретические вопросы, практические упражнения. Лекции можно было слушать/смотреть либо на сайте либо можно было скачать видеоматериалы и изучать их в не зависимости есть у вас доступ в Интернет или нет. В ходе лекции кроме объяснений теоретической части, приводилось много примеров. Это помогало лучше понять принципы и идеи использования различных подходов машинного обучения. Теоретическая часть хорошо сочеталась с вопросами к каждой теме. Буквально с первых занятий ушел некий “страх” ответить неправильно на вопросы или недобрать необходимых 5 баллов. Вопросы/ответы построены именно на то, чтобы в конечном счете лучше понять курс. Тесты можно было проходить по несколько раз.  Для всех ответов правильных и неправильных давались краткие пояснения, почему это правильно или почему нет. Часто я проходил тесты по несколько раз именно для того, чтобы проверить правильно я понял материал или нет.&lt;br /&gt;
&lt;br /&gt;
Для тех, кто записался на курс по расширенной программе, необходимо было выполнить еще и практические занятия. На основе &lt;a href="http://www.gnu.org/software/octave/"&gt;Octave&lt;/a&gt; моделировались различные ситуации применения алгоритмов машинного обучения на практике - кластеризация, предсказания, распознавание рукописного текста и изображений, рекомендательные системы и много другое. Результаты упражнений необходимо регистрировать через специальную систему оценки результатов либо прямо из Octave либо через web форму. &lt;br /&gt;
&lt;br /&gt;
Совет: перед началом курса стоит пройти или повторить &lt;a href="http://www.khanacademy.org/#linear-algebra"&gt;курс линейной алгебры&lt;/a&gt;. В основном практические занятия построены на работе с матрицами, умение с ними работать позволит сократить время на выполнение упражнений.&lt;br /&gt;
&lt;br /&gt;
Курс очень понравился, даже есть некое чувство сожаления, что курс закончился. Но впереди новый год, и в следующем году университет Стендфорда подготовил ряд новых курсов:&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;&lt;a href="http://www.launchpad-class.org/"&gt;Lean Launchpad&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.venture-class.org/"&gt;Technology Entrepreneurship&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.anatomy-class.org/"&gt;Anatomy&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.greenbuilding-class.org/"&gt;Making Green Buildings&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.infotheory-class.org/"&gt;Information Teory&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.modelthinker-class.org/"&gt;Model Thinking&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.cs101-class.org/"&gt;Computer Science CS101&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://jan2012.ml-class.org/"&gt;Machine learning&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.saas-class.org/"&gt;Software as a service&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.hci-class.org/"&gt;Human-Computer Interaction&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.nlp-class.org/"&gt;Natural Language Processing&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.game-theory-class.org/"&gt;Game Theory&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.pgm-class.org/"&gt;Probabilistic Graphical Models&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.crypto-class.org/"&gt;Cryptography&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.algo-class.org/"&gt;Design and Analysis of Algorithms I&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.security-class.org/"&gt;Computer Security&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2025136836330523605-9129425462683115556?l=devel.ownport.net' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/develforfun/~4/h2ReH8CbTq8" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://devel.ownport.net/feeds/9129425462683115556/comments/default" title="Комментарии к сообщению" /><link rel="replies" type="text/html" href="http://devel.ownport.net/2011/12/blog-post.html#comment-form" title="Комментарии: 0" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/2025136836330523605/posts/default/9129425462683115556?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/2025136836330523605/posts/default/9129425462683115556?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/develforfun/~3/h2ReH8CbTq8/blog-post.html" title="Курс &quot;Машинное обучение&quot;, впечатления" /><author><name>d.rey</name><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://2.bp.blogspot.com/--plt9AbvrJo/Togs-7fb1hI/AAAAAAAAAbE/vtjk9PqI9jM/s72-c/machine_learning.png" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://devel.ownport.net/2011/12/blog-post.html</feedburner:origLink></entry></feed>

