<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>ZetBlog&#187; Python</title>
	<atom:link href="http://zetblog.ru/tag/python/feed/" rel="self" type="application/rss+xml" />
	<link>http://zetblog.ru</link>
	<description>Зеты говорят. Блог о программировании, администрировании и безопасности.</description>
	<lastBuildDate>Sat, 29 Oct 2011 18:59:40 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>Python: Маленькая хитрость. if-else vs and-or.</title>
		<link>http://zetblog.ru/programming/201003/python-if-else-vs-and-or/</link>
		<comments>http://zetblog.ru/programming/201003/python-if-else-vs-and-or/#comments</comments>
		<pubDate>Wed, 17 Mar 2010 19:30:57 +0000</pubDate>
		<dc:creator>lizz</dc:creator>
				<category><![CDATA[общие вопросы]]></category>
		<category><![CDATA[Программирование]]></category>
		<category><![CDATA[hints]]></category>
		<category><![CDATA[Python]]></category>

		<guid isPermaLink="false">http://zetblog.ru/?p=980</guid>
		<description><![CDATA[На этот раз будет мини-заметка, уж слишком мне понравился трюк, о котором пойдёт речь дальше :). Наверное любому программисту приходится часто писать конструкции такого вида: if a == b: c = d else: c = e Как-то разбирая исходники какого-то проекта наткнулся на весьма компактную замену. Вот для сравнения два аналогичных блока кода с использованием [...]]]></description>
			<content:encoded><![CDATA[<p>На этот раз будет мини-заметка, уж слишком мне понравился трюк, о котором пойдёт речь дальше :). </p>
<p>Наверное любому программисту приходится часто писать конструкции такого вида:</p>
<pre class=".brush: python">if a == b:
    c = d
else:
    c = e</pre>
<p>Как-то разбирая исходники какого-то проекта наткнулся на весьма компактную замену. Вот для сравнения два аналогичных блока кода с использованием логических операций python&#8217;а и с использованием конструкции if-else:</p>
<pre class=".brush: python"># if-else:
if random.random() > 0.5:
    a = 1
else:
    a = 0

# and-or style:
a = random.random() > 0.5 and 1 or 0</pre>
<p>На мой взгляд выглядит гораздо лучше и компактнее (да-да, if-else можно записать в 2 строчки вместо 4, но мне так не нравится ^__^) . Другое дело, что некоторым это может показаться противоречиво с некоторыми пунктами дзена python&#8217;а (import this), но это спорно :). В общем использую там, где считаю нужным.</p>
<p>Кстати, если кого-то интересует производительность, то она примерно одинакова, далее выложу тесты и объяснение логики для тех, кому интересно.<br />
<span id="more-980"></span></p>
<pre class=".brush: python">>>> import timeit
>>> t1 = timeit.Timer('if random.random()>0.5:a=1\nelse:a =0', 'from __main__ import a\nimport random')
>>> t2 = timeit.Timer('a=random.random()>0.5 and 1 or 0', 'from __main__ import a\nimport random')
>>> t1.repeat()
[0.21074632467116317, 0.2097615509806019, 0.20978293771349854]
>>> t2.repeat()
[0.21944338095772764, 0.21785226684687586, 0.21940797240040411]
</pre>
<p>Тесты привёл, теперь объяснение.</p>
<p>Дело в том, что логические операции <strong>and</strong> и <strong>or</strong> в python&#8217;е возвращают один из операндов. Операция and возвращает первый операнд, если он приводится к логическому типу False, иначе &#8212; второй. Операция or наоборот, возвращает 1й операнд, если он приводится к типу True, иначе &#8212; второй. Всё это связано с &#171;ленивостью&#187; (lazy) операций, вычисляется столько аргументов, сколько надо для того, чтобы однозначно определить результат (например, 1 or x всегда даёт True, поэтому x не вычисляется).</p>
]]></content:encoded>
			<wfw:commentRss>http://zetblog.ru/programming/201003/python-if-else-vs-and-or/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Hibernate: Удаление объектов из БД.</title>
		<link>http://zetblog.ru/programming/201002/hibernate-%d1%83%d0%b4%d0%b0%d0%bb%d0%b5%d0%bd%d0%b8%d0%b5-%d0%be%d0%b1%d1%8a%d0%b5%d0%ba%d1%82%d0%be%d0%b2-%d0%b8%d0%b7-%d0%b1%d0%b4/</link>
		<comments>http://zetblog.ru/programming/201002/hibernate-%d1%83%d0%b4%d0%b0%d0%bb%d0%b5%d0%bd%d0%b8%d0%b5-%d0%be%d0%b1%d1%8a%d0%b5%d0%ba%d1%82%d0%be%d0%b2-%d0%b8%d0%b7-%d0%b1%d0%b4/#comments</comments>
		<pubDate>Wed, 10 Feb 2010 10:35:29 +0000</pubDate>
		<dc:creator>lizz</dc:creator>
				<category><![CDATA[Программирование]]></category>
		<category><![CDATA[Hibernate]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[Jython]]></category>
		<category><![CDATA[ORM]]></category>
		<category><![CDATA[Python]]></category>

		<guid isPermaLink="false">http://zetblog.ru/?p=921</guid>
		<description><![CDATA[По работе пришлось изучать работу Java&#8217;вского ORM&#8217;а, пока что знаком только бегло, но некоторые полезные штуки для новичка решил записать. Может кому пригодится, может нет, но хотя бы самому гуглить придётся меньше =). Кстати, примеры будут не на Java, а на Jython&#8217;е, т.к. с первым я тоже не очень знаком :). Итак, опустим настройку и [...]]]></description>
			<content:encoded><![CDATA[<p>По работе пришлось изучать работу Java&#8217;вского ORM&#8217;а, пока что знаком только бегло, но некоторые полезные штуки для новичка решил записать. Может кому пригодится, может нет, но хотя бы самому гуглить придётся меньше =). Кстати, примеры будут не на Java, а на Jython&#8217;е, т.к. с первым я тоже не очень знаком :).</p>
<p>Итак, опустим настройку и подключение Hibernate, предположим, что вы это уже сделали :). Быть может, напишу об этом позже. Требуется удалить из таблицы player (которая маппится с классом Player, естественно&#8230; или наоборот :) ) некоторые записи. Если мы знаем id игрока, тогда всё элементарно (как и в других случаях)):</p>
<div class="codesnip-container" >
<div class="python codesnip" style="font-family:monospace;">player = session.<span class="me1">load</span><span class="br0">&#40;</span>Player, player_id<span class="br0">&#41;</span><br />
session.<span class="me1">delete</span><span class="br0">&#40;</span>player<span class="br0">&#41;</span></div>
</div>
<p>Теперь рассмотрим случай, когда надо удалить много записей.<span id="more-921"></span></p>
<p>В ORM&#8217;е Hibernate несколько способов провернуть это. 1й &#8212; очевидный, с помощью createQuery выбрать все нужные записи HQL&#8217;ом и в цикле удалять по одной:</p>
<pre>
<div class="codesnip-container" >
<div class="python codesnip" style="font-family:monospace;">players_list = session.<span class="me1">createQuery</span><span class="br0">&#40;</span><span class="st0">&quot;FROM Player WHERE name = :name&quot;</span><span class="br0">&#41;</span>\
&nbsp; &nbsp; .<span class="me1">setParameter</span><span class="br0">&#40;</span><span class="st0">&quot;name&quot;</span>, <span class="st0">&quot;Василий&quot;</span><span class="br0">&#41;</span>\
&nbsp; &nbsp; .<span class="kw2">list</span><span class="br0">&#40;</span><span class="br0">&#41;</span>
<span class="kw1">for</span> player <span class="kw1">in</span> players_list:
&nbsp; &nbsp; session.<span class="me1">delete</span><span class="br0">&#40;</span>player<span class="br0">&#41;</span></div>
</div>
</pre>
<p>Но это влечёт накладные расходы на получение всех нужных объектов, а затем удаление по одному, в таком случае мы выполним столько sql-запросов, сколько объектов загрузили, что может ухудшить производительность приложения. Для этого есть другой способ. Вот в общем то и он:</p>
<div class="codesnip-container" >
<div class="python codesnip" style="font-family:monospace;">session.<span class="me1">createQuery</span><span class="br0">&#40;</span><span class="st0">&quot;DELETE Player WHERE name = :name&quot;</span><span class="br0">&#41;</span>\<br />
&nbsp; &nbsp; .<span class="me1">setParameter</span><span class="br0">&#40;</span><span class="st0">&quot;name&quot;</span>, <span class="st0">&quot;Василий&quot;</span><span class="br0">&#41;</span>\<br />
&nbsp; &nbsp; .<span class="me1">executeUpdate</span><span class="br0">&#40;</span><span class="br0">&#41;</span></div>
</div>
<p>Вот таким способом можно избавиться от всех неугодных нам Василиев ;). Так же есть возможность воспользоваться сырым sql с помощью Session.createSQLQuery().</p>
<p>Ссылки:<br />
<a href="http://docs.jboss.org/hibernate/stable/core/reference/en/html/batch.html#batch-direct">Документация по Hibernate</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://zetblog.ru/programming/201002/hibernate-%d1%83%d0%b4%d0%b0%d0%bb%d0%b5%d0%bd%d0%b8%d0%b5-%d0%be%d0%b1%d1%8a%d0%b5%d0%ba%d1%82%d0%be%d0%b2-%d0%b8%d0%b7-%d0%b1%d0%b4/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Python: Реализация простого web-сервера.</title>
		<link>http://zetblog.ru/programming/200911/python-simple-web-server/</link>
		<comments>http://zetblog.ru/programming/200911/python-simple-web-server/#comments</comments>
		<pubDate>Mon, 02 Nov 2009 16:26:00 +0000</pubDate>
		<dc:creator>lizz</dc:creator>
				<category><![CDATA[web]]></category>
		<category><![CDATA[Программирование]]></category>
		<category><![CDATA[BaseHTTPServer]]></category>
		<category><![CDATA[HTTP]]></category>
		<category><![CDATA[Python]]></category>

		<guid isPermaLink="false">http://zetblog.ru/?p=757</guid>
		<description><![CDATA[Не для собственных нужд, но как-то понадобилось написать простой web-сервер для обработки на нём загруженных данных. В общем-то должен был получиться простой вёб-интерфейс к программе. Он и получился, местами даже слишком простой. В общем суть такова &#8212; необходимо получить от пользователя экзешник, на сервере его обработать нужными программами и выдать результат, т.е. обработанный файл для [...]]]></description>
			<content:encoded><![CDATA[<p>Не для собственных нужд, но как-то понадобилось написать простой web-сервер для обработки на нём загруженных данных. В общем-то должен был получиться простой вёб-интерфейс к программе. Он и получился, местами даже слишком простой. В общем суть такова &#8212; необходимо получить от пользователя экзешник, на сервере его обработать нужными программами и выдать результат, т.е. обработанный файл для скачивания. Можно было бы написать скрипт на php, что было бы проще, но тогда необходимо с собой таскать какой-нибудь вёб-сервер (apache, denwer и т.п.). На питоне можно его реализовать достаточно просто в самом скрипте используя стандартные заготовки и библиотеки, такие как BaseHTTPServer. Ниже следует листинг с краткими комментариями.<br />
<span id="more-757"></span></p>
<pre>
<div class="codesnip-container" >
<div class="python codesnip" style="font-family:monospace;"><span class="co1"># -*- coding: utf-8 -*-</span>

<span class="kw1">import</span> <span class="kw3">cgi</span>
<span class="kw1">from</span> <span class="kw3">os</span> <span class="kw1">import</span> curdir, sep
<span class="kw1">from</span> <span class="kw3">BaseHTTPServer</span> <span class="kw1">import</span> BaseHTTPRequestHandler, HTTPServer
<span class="kw1">import</span> <span class="kw3">subprocess</span>

<span class="kw1">class</span> MyHandler<span class="br0">&#40;</span>BaseHTTPRequestHandler<span class="br0">&#41;</span>:
&nbsp; &nbsp; <span class="kw1">def</span> do_GET<span class="br0">&#40;</span><span class="kw2">self</span><span class="br0">&#41;</span>:
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">try</span>:
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="kw2">self</span>.<span class="me1">path</span> <span class="sy0">!</span>= <span class="st0">&quot;/output.exe&quot;</span>:
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; f = <span class="kw2">open</span><span class="br0">&#40;</span>curdir+sep+<span class="st0">&quot;upload.html&quot;</span><span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">self</span>.<span class="me1">send_response</span><span class="br0">&#40;</span>200<span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">self</span>.<span class="me1">send_header</span><span class="br0">&#40;</span><span class="st0">&quot;Content-type&quot;</span>, <span class="st0">&quot;text/html&quot;</span><span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">self</span>.<span class="me1">end_headers</span><span class="br0">&#40;</span><span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">self</span>.<span class="me1">wfile</span>.<span class="me1">write</span><span class="br0">&#40;</span>f.<span class="me1">read</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; f.<span class="me1">close</span><span class="br0">&#40;</span><span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">else</span>:
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">self</span>.<span class="me1">send_response</span><span class="br0">&#40;</span>200<span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">self</span>.<span class="me1">send_header</span><span class="br0">&#40;</span><span class="st0">&quot;Content-type&quot;</span>, <span class="st0">&quot;application/octet-stream&quot;</span><span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">self</span>.<span class="me1">end_headers</span><span class="br0">&#40;</span><span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">self</span>.<span class="me1">wfile</span>.<span class="me1">write</span><span class="br0">&#40;</span><span class="kw2">open</span><span class="br0">&#40;</span>curdir+sep+<span class="st0">&quot;output.exe&quot;</span>, <span class="st0">&quot;rb&quot;</span><span class="br0">&#41;</span>.<span class="me1">read</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">except</span> <span class="kw2">IOError</span>:
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">self</span>.<span class="me1">send_error</span><span class="br0">&#40;</span><span class="nu0">404</span>,<span class="st0">&quot;File Not Found: %s&quot;</span> <span class="sy0">%</span> <span class="kw2">self</span>.<span class="me1">path</span><span class="br0">&#41;</span>

&nbsp; &nbsp; <span class="kw1">def</span> do_POST<span class="br0">&#40;</span><span class="kw2">self</span><span class="br0">&#41;</span>:
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">try</span>:
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ctype, pdict = <span class="kw3">cgi</span>.<span class="me1">parse_header</span><span class="br0">&#40;</span><span class="kw2">self</span>.<span class="me1">headers</span>.<span class="me1">getheader</span><span class="br0">&#40;</span><span class="st0">&quot;content-type&quot;</span><span class="br0">&#41;</span><span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> ctype == <span class="st0">&quot;multipart/form-data&quot;</span>:
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; query = <span class="kw3">cgi</span>.<span class="me1">parse_multipart</span><span class="br0">&#40;</span><span class="kw2">self</span>.<span class="me1">rfile</span>, pdict<span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">self</span>.<span class="me1">send_response</span><span class="br0">&#40;</span>200<span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">self</span>.<span class="me1">end_headers</span><span class="br0">&#40;</span><span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; upfile = query.<span class="me1">get</span><span class="br0">&#40;</span><span class="st0">&quot;file&quot;</span><span class="br0">&#41;</span>

&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; f = <span class="kw2">open</span><span class="br0">&#40;</span>curdir+sep+<span class="st0">&quot;output.exe&quot;</span>, <span class="st0">&quot;wb&quot;</span><span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; f.<span class="me1">write</span><span class="br0">&#40;</span>upfile<span class="br0">&#91;</span><span class="nu0">0</span><span class="br0">&#93;</span><span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; f.<span class="me1">close</span><span class="br0">&#40;</span><span class="br0">&#41;</span>

&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; params = <span class="st0">&quot; np output.exe&quot;</span>

&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; p = query.<span class="me1">get</span><span class="br0">&#40;</span><span class="st0">&quot;encryption&quot;</span><span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> p<span class="br0">&#91;</span><span class="nu0">0</span><span class="br0">&#93;</span> == <span class="st0">&quot;aes&quot;</span>:
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; params += <span class="st0">&quot; sf 1&quot;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">elif</span> p<span class="br0">&#91;</span><span class="nu0">0</span><span class="br0">&#93;</span> == <span class="st0">&quot;rc5&quot;</span>:
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; params += <span class="st0">&quot; sf 2&quot;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">elif</span> p<span class="br0">&#91;</span><span class="nu0">0</span><span class="br0">&#93;</span> == <span class="st0">&quot;xor&quot;</span>:
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; params += <span class="st0">&quot; sf 3&quot;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">else</span>:
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; params += <span class="st0">&quot; sf 0&quot;</span>

&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; p = query.<span class="me1">get</span><span class="br0">&#40;</span><span class="st0">&quot;hw_bind&quot;</span><span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> p<span class="br0">&#91;</span><span class="nu0">0</span><span class="br0">&#93;</span> == <span class="st0">&quot;yes&quot;</span>:
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; p = query.<span class="me1">get</span><span class="br0">&#40;</span><span class="st0">&quot;hw_bind_serial&quot;</span><span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">assert</span> <span class="kw2">len</span><span class="br0">&#40;</span>p<span class="br0">&#91;</span><span class="nu0">0</span><span class="br0">&#93;</span><span class="br0">&#41;</span> == <span class="nu0">8</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; params += <span class="st0">&quot; sn &quot;</span> + p<span class="br0">&#91;</span>0<span class="br0">&#93;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">else</span>:
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; params += <span class="st0">&quot; sn 0&quot;</span>

&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; p = query.<span class="me1">get</span><span class="br0">&#40;</span><span class="st0">&quot;passwd&quot;</span><span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">assert</span> <span class="kw2">len</span><span class="br0">&#40;</span>p<span class="br0">&#91;</span>0<span class="br0">&#93;</span><span class="br0">&#41;</span> <span class="sy0">&amp;</span>gt<span class="sy0">;</span> <span class="nu0">0</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; params += <span class="st0">&quot; pass &quot;</span> + p<span class="br0">&#91;</span><span class="nu0">0</span><span class="br0">&#93;</span>

&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; p = query.<span class="me1">get</span><span class="br0">&#40;</span><span class="st0">&quot;pack&quot;</span><span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> p<span class="br0">&#91;</span><span class="nu0">0</span><span class="br0">&#93;</span> == <span class="st0">&quot;yes&quot;</span>:
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; params += <span class="st0">&quot; pack 1&quot;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">else</span>:
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; params += <span class="st0">&quot; pack 0&quot;</span>

&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; pipe = <span class="kw3">subprocess</span>.<span class="me1">Popen</span><span class="br0">&#40;</span><span class="st0">&quot;processor.exe &quot;</span>+params, shell=<span class="kw2">True</span>, stdin=<span class="kw3">subprocess</span>.<span class="me1">PIPE</span>, stdout=<span class="kw3">subprocess</span>.<span class="me1">PIPE</span>, stderr=<span class="kw3">subprocess</span>.<span class="me1">PIPE</span><span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; pipe.<span class="me1">stdin</span>.<span class="me1">close</span><span class="br0">&#40;</span><span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; pipe.<span class="me1">wait</span><span class="br0">&#40;</span><span class="br0">&#41;</span>

&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">self</span>.<span class="me1">wfile</span>.<span class="me1">write</span><span class="br0">&#40;</span><span class="st0">'&lt;a href=&quot;/output.exe&quot;&gt;Download results&lt;/a&gt;.'</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">except</span> :
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">pass</span>

<span class="kw1">if</span> __name__ == <span class="st0">&quot;__main__&quot;</span>:
&nbsp; &nbsp; <span class="kw1">try</span>:
&nbsp; &nbsp; &nbsp; &nbsp; server = HTTPServer<span class="br0">&#40;</span><span class="br0">&#40;</span><span class="st0">&quot;&quot;</span>, 8080<span class="br0">&#41;</span>, MyHandler<span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">print</span> <span class="st0">&quot;started httpserver...&quot;</span>
&nbsp; &nbsp; &nbsp; &nbsp; server.<span class="me1">serve_forever</span><span class="br0">&#40;</span><span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="kw1">except</span> <span class="kw2">KeyboardInterrupt</span>:
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">print</span> <span class="st0">&quot;^C received, shutting down server&quot;</span>
&nbsp; &nbsp; &nbsp; &nbsp; server.<span class="kw3">socket</span>.<span class="me1">close</span><span class="br0">&#40;</span><span class="br0">&#41;</span></div>
</div>
</pre>
<p>Итак, для начала импортируем из библиотеки BaseHTTPServer два класса: HTTPserver — собственно, сам вёб-сервер и BaseHTTPRequestHandler — класс, который служит для обработки запросов от пользователей.</p>
<p>Объявляем свой класс MyHandler, который наследуется от BaseHTTPRequestHandler. И перегружаем в нём два метода — do_GET и do_POST для обработки данных, переданных методом GET и POST, соответственно.</p>
<p>В первом обработчике проверяем запрос от пользователя (содержится в  self.path), если запрашиваемый документ не является /output.exe, то выдаём форму для загрузки файла, иначе — считываем и выдаём output.exe. Так же, перед этим, посылается ответ от сервера с кодом 200, что соответствует успешной обработке запроса от клиента и передаём заголовок, в котором указан тип содержимого (text/html для html-код или application/octet-stream для бинарного файла).</p>
<p>В обработке POST-запроса проверяем какие данные были переданы. Сначала получаем файл и записываем его под именем output.exe. Далее формируем строку параметров на основе переданных от пользователя данных, запускаем хранящуюся на сервере программу для обработки полученных файлов, ждём пока она завершится и выдаём ссылку на скачивание результата.</p>
<p>Далее, в самой программе создаём вёб-сервер, указав при этом порт, на котором он будет работать (в примере это 8080) и класс, который необходимо использовать для обработки запросов от пользователей.</p>
<p>Недостаток заключается в том, что данная реализация не сможет обработать одновременную загрузку файлов от разных пользователей, т.к. в лучшем случае просто один из запросов затрёт файл output.exe, полученный в другом запросе. Но такая задача не стояла. На мой взгляд хороший пример для демонстрации возможностей python&#8217;а.</p>
<p>Так же код html-файла upload.html, который должен располагаться в той же директории, что и сервер:</p>
<pre>
<div class="codesnip-container" >
<div class="html4strict codesnip" style="font-family:monospace;"><span class="sc2">&lt;<a href="http://december.com/html/4/element/form.html"><span class="kw2">form</span></a> <span class="kw3">action</span><span class="sy0">=</span><span class="st0">&quot;/&quot;</span> <span class="kw3">enctype</span><span class="sy0">=</span><span class="st0">&quot;multipart/form-data&quot;</span> <span class="kw3">method</span><span class="sy0">=</span><span class="st0">&quot;post&quot;</span>&gt;</span>
<span class="sc2">&lt;<a href="http://december.com/html/4/element/table.html"><span class="kw2">table</span></a> <span class="kw3">border</span><span class="sy0">=</span><span class="st0">&quot;1&quot;</span>&gt;</span>
<span class="sc2">&lt;<a href="http://december.com/html/4/element/tbody.html"><span class="kw2">tbody</span></a>&gt;</span>
<span class="sc2">&lt;<a href="http://december.com/html/4/element/tr.html"><span class="kw2">tr</span></a>&gt;</span>
<span class="sc2">&lt;<a href="http://december.com/html/4/element/td.html"><span class="kw2">td</span></a>&gt;</span>Encryption:<span class="sc2">&lt;<span class="sy0">/</span><a href="http://december.com/html/4/element/td.html"><span class="kw2">td</span></a>&gt;</span>
<span class="sc2">&lt;<a href="http://december.com/html/4/element/td.html"><span class="kw2">td</span></a>&gt;</span>
<span class="sc2">&lt;<a href="http://december.com/html/4/element/input.html"><span class="kw2">input</span></a> <span class="kw3">checked</span><span class="sy0">=</span><span class="st0">&quot;checked&quot;</span> <span class="kw3">name</span><span class="sy0">=</span><span class="st0">&quot;encryption&quot;</span> <span class="kw3">type</span><span class="sy0">=</span><span class="st0">&quot;radio&quot;</span> <span class="kw3">value</span><span class="sy0">=</span><span class="st0">&quot;none&quot;</span> <span class="sy0">/</span>&gt;</span>None
<span class="sc2">&lt;<a href="http://december.com/html/4/element/input.html"><span class="kw2">input</span></a> <span class="kw3">name</span><span class="sy0">=</span><span class="st0">&quot;encryption&quot;</span> <span class="kw3">type</span><span class="sy0">=</span><span class="st0">&quot;radio&quot;</span> <span class="kw3">value</span><span class="sy0">=</span><span class="st0">&quot;aes&quot;</span> <span class="sy0">/</span>&gt;</span>AES
<span class="sc2">&lt;<a href="http://december.com/html/4/element/input.html"><span class="kw2">input</span></a> <span class="kw3">name</span><span class="sy0">=</span><span class="st0">&quot;encryption&quot;</span> <span class="kw3">type</span><span class="sy0">=</span><span class="st0">&quot;radio&quot;</span> <span class="kw3">value</span><span class="sy0">=</span><span class="st0">&quot;rc5&quot;</span> <span class="sy0">/</span>&gt;</span>RC5
<span class="sc2">&lt;<a href="http://december.com/html/4/element/input.html"><span class="kw2">input</span></a> <span class="kw3">name</span><span class="sy0">=</span><span class="st0">&quot;encryption&quot;</span> <span class="kw3">type</span><span class="sy0">=</span><span class="st0">&quot;radio&quot;</span> <span class="kw3">value</span><span class="sy0">=</span><span class="st0">&quot;xor&quot;</span> <span class="sy0">/</span>&gt;</span>XOR<span class="sc2">&lt;<span class="sy0">/</span><a href="http://december.com/html/4/element/td.html"><span class="kw2">td</span></a>&gt;</span>
<span class="sc2">&lt;<span class="sy0">/</span><a href="http://december.com/html/4/element/tr.html"><span class="kw2">tr</span></a>&gt;</span>
<span class="sc2">&lt;<a href="http://december.com/html/4/element/tr.html"><span class="kw2">tr</span></a>&gt;</span>
<span class="sc2">&lt;<a href="http://december.com/html/4/element/td.html"><span class="kw2">td</span></a>&gt;</span>Hardware binding:<span class="sc2">&lt;<span class="sy0">/</span><a href="http://december.com/html/4/element/td.html"><span class="kw2">td</span></a>&gt;</span>
<span class="sc2">&lt;<a href="http://december.com/html/4/element/td.html"><span class="kw2">td</span></a>&gt;</span>
<span class="sc2">&lt;<a href="http://december.com/html/4/element/input.html"><span class="kw2">input</span></a> <span class="kw3">checked</span><span class="sy0">=</span><span class="st0">&quot;checked&quot;</span> <span class="kw3">name</span><span class="sy0">=</span><span class="st0">&quot;hw_bind&quot;</span> <span class="kw3">type</span><span class="sy0">=</span><span class="st0">&quot;radio&quot;</span> <span class="kw3">value</span><span class="sy0">=</span><span class="st0">&quot;no&quot;</span> <span class="sy0">/</span>&gt;</span>No
<span class="sc2">&lt;<a href="http://december.com/html/4/element/input.html"><span class="kw2">input</span></a> <span class="kw3">name</span><span class="sy0">=</span><span class="st0">&quot;hw_bind&quot;</span> <span class="kw3">type</span><span class="sy0">=</span><span class="st0">&quot;radio&quot;</span> <span class="kw3">value</span><span class="sy0">=</span><span class="st0">&quot;yes&quot;</span> <span class="sy0">/</span>&gt;</span>Yes
<span class="sc2">&lt;<a href="http://december.com/html/4/element/input.html"><span class="kw2">input</span></a> <span class="kw3">name</span><span class="sy0">=</span><span class="st0">&quot;hw_bind_serial&quot;</span> <span class="kw3">value</span><span class="sy0">=</span><span class="st0">&quot;media serial number&quot;</span> <span class="sy0">/</span>&gt;&lt;<span class="sy0">/</span><a href="http://december.com/html/4/element/td.html"><span class="kw2">td</span></a>&gt;</span>
<span class="sc2">&lt;<span class="sy0">/</span><a href="http://december.com/html/4/element/tr.html"><span class="kw2">tr</span></a>&gt;</span>
<span class="sc2">&lt;<a href="http://december.com/html/4/element/tr.html"><span class="kw2">tr</span></a>&gt;</span>
<span class="sc2">&lt;<a href="http://december.com/html/4/element/td.html"><span class="kw2">td</span></a>&gt;</span>Password:<span class="sc2">&lt;<span class="sy0">/</span><a href="http://december.com/html/4/element/td.html"><span class="kw2">td</span></a>&gt;</span>
<span class="sc2">&lt;<a href="http://december.com/html/4/element/td.html"><span class="kw2">td</span></a>&gt;</span>
<span class="sc2">&lt;<a href="http://december.com/html/4/element/input.html"><span class="kw2">input</span></a> <span class="kw3">name</span><span class="sy0">=</span><span class="st0">&quot;passwd&quot;</span> <span class="kw3">type</span><span class="sy0">=</span><span class="st0">&quot;password&quot;</span> <span class="sy0">/</span>&gt;&lt;<span class="sy0">/</span><a href="http://december.com/html/4/element/td.html"><span class="kw2">td</span></a>&gt;</span>
<span class="sc2">&lt;<span class="sy0">/</span><a href="http://december.com/html/4/element/tr.html"><span class="kw2">tr</span></a>&gt;</span>
<span class="sc2">&lt;<a href="http://december.com/html/4/element/tr.html"><span class="kw2">tr</span></a>&gt;</span>
<span class="sc2">&lt;<a href="http://december.com/html/4/element/td.html"><span class="kw2">td</span></a>&gt;</span>Pack:<span class="sc2">&lt;<span class="sy0">/</span><a href="http://december.com/html/4/element/td.html"><span class="kw2">td</span></a>&gt;</span>
<span class="sc2">&lt;<a href="http://december.com/html/4/element/td.html"><span class="kw2">td</span></a>&gt;</span>
<span class="sc2">&lt;<a href="http://december.com/html/4/element/input.html"><span class="kw2">input</span></a> <span class="kw3">checked</span><span class="sy0">=</span><span class="st0">&quot;checked&quot;</span> <span class="kw3">name</span><span class="sy0">=</span><span class="st0">&quot;pack&quot;</span> <span class="kw3">type</span><span class="sy0">=</span><span class="st0">&quot;radio&quot;</span> <span class="kw3">value</span><span class="sy0">=</span><span class="st0">&quot;no&quot;</span> <span class="sy0">/</span>&gt;</span>No
<span class="sc2">&lt;<a href="http://december.com/html/4/element/input.html"><span class="kw2">input</span></a> <span class="kw3">name</span><span class="sy0">=</span><span class="st0">&quot;pack&quot;</span> <span class="kw3">type</span><span class="sy0">=</span><span class="st0">&quot;radio&quot;</span> <span class="kw3">value</span><span class="sy0">=</span><span class="st0">&quot;yes&quot;</span> <span class="sy0">/</span>&gt;</span>Yes<span class="sc2">&lt;<span class="sy0">/</span><a href="http://december.com/html/4/element/td.html"><span class="kw2">td</span></a>&gt;</span>
<span class="sc2">&lt;<span class="sy0">/</span><a href="http://december.com/html/4/element/tr.html"><span class="kw2">tr</span></a>&gt;</span>
<span class="sc2">&lt;<a href="http://december.com/html/4/element/tr.html"><span class="kw2">tr</span></a>&gt;</span>
<span class="sc2">&lt;<a href="http://december.com/html/4/element/td.html"><span class="kw2">td</span></a> <span class="kw3">colspan</span><span class="sy0">=</span><span class="st0">&quot;2&quot;</span>&gt;</span>
<span class="sc2">&lt;<a href="http://december.com/html/4/element/input.html"><span class="kw2">input</span></a> <span class="kw3">name</span><span class="sy0">=</span><span class="st0">&quot;file&quot;</span> <span class="kw3">type</span><span class="sy0">=</span><span class="st0">&quot;file&quot;</span> <span class="sy0">/</span>&gt;</span>
<span class="sc2">&lt;<a href="http://december.com/html/4/element/input.html"><span class="kw2">input</span></a> <span class="kw3">type</span><span class="sy0">=</span><span class="st0">&quot;submit&quot;</span> <span class="kw3">value</span><span class="sy0">=</span><span class="st0">&quot;Отправить&quot;</span> <span class="sy0">/</span>&gt;&lt;<span class="sy0">/</span><a href="http://december.com/html/4/element/td.html"><span class="kw2">td</span></a>&gt;</span>
<span class="sc2">&lt;<span class="sy0">/</span><a href="http://december.com/html/4/element/tr.html"><span class="kw2">tr</span></a>&gt;</span>
<span class="sc2">&lt;<span class="sy0">/</span><a href="http://december.com/html/4/element/tbody.html"><span class="kw2">tbody</span></a>&gt;&lt;<span class="sy0">/</span><a href="http://december.com/html/4/element/table.html"><span class="kw2">table</span></a>&gt;</span>
<span class="sc2">&lt;<span class="sy0">/</span><a href="http://december.com/html/4/element/form.html"><span class="kw2">form</span></a>&gt;</span></div>
</div>
</pre>
<p>Ссылки к статье:<br />
<a href="http://ru.wikipedia.org/wiki/%D0%A1%D0%BF%D0%B8%D1%81%D0%BE%D0%BA_%D0%BA%D0%BE%D0%B4%D0%BE%D0%B2_%D1%81%D0%BE%D1%81%D1%82%D0%BE%D1%8F%D0%BD%D0%B8%D1%8F_HTTP"><br />
http://ru.wikipedia.org/wiki/Список_кодов_состояния_HTTP</a> &#8212; Список кодов состояния HTTP.</p>
]]></content:encoded>
			<wfw:commentRss>http://zetblog.ru/programming/200911/python-simple-web-server/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Python: Проблема с подвисанием GUI на TkInter.</title>
		<link>http://zetblog.ru/programming/200910/python-tkinter-antifreeze/</link>
		<comments>http://zetblog.ru/programming/200910/python-tkinter-antifreeze/#comments</comments>
		<pubDate>Wed, 21 Oct 2009 18:57:03 +0000</pubDate>
		<dc:creator>lizz</dc:creator>
				<category><![CDATA[общие вопросы]]></category>
		<category><![CDATA[прикладное]]></category>
		<category><![CDATA[Программирование]]></category>
		<category><![CDATA[GUI]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[TkInter]]></category>

		<guid isPermaLink="false">http://zetblog.ru/?p=731</guid>
		<description><![CDATA[Встала задача написания небольшой графической оболочки для программы с минимальным интерфейсом (одна кнопка и одно поле вывода). Много нам не надо, поэтому решил обойтись идущей вместе с python&#8217;ом в поставке библиотекой TkInter. И тут столкнулся с небольшой проблемой &#8212; при нажатии кнопки запускаются довольно долгие и объёмные вычисления, из-за которых виснет весь интерфейс программы. Решений [...]]]></description>
			<content:encoded><![CDATA[<p>Встала задача написания небольшой графической оболочки для программы с минимальным интерфейсом (одна кнопка и одно поле вывода). Много нам не надо, поэтому решил обойтись идущей вместе с python&#8217;ом в поставке библиотекой TkInter. И тут столкнулся с небольшой проблемой &#8212; при нажатии кнопки запускаются довольно долгие и объёмные вычисления, из-за которых виснет весь интерфейс программы.<br />
<span id="more-731"></span></p>
<p>Решений у этого вопроса несколько.<br />
1 &#8212; Запускать эти вычисления в отдельном потоке, что меня вполне устроило:</p>
<pre>
<div class="codesnip-container" >
<div class="python codesnip" style="font-family:monospace;"><span class="co1"># -*- coding: utf-8 -*-</span>
<span class="kw1">from</span> <span class="kw3">Tkinter</span> <span class="kw1">import</span> <span class="sy0">*</span>
<span class="kw1">import</span> <span class="kw3">threading</span>, <span class="kw3">time</span>

<span class="kw1">class</span> AppGUI:
&nbsp; &nbsp; <span class="kw1">def</span> <span class="kw4">__init__</span><span class="br0">&#40;</span><span class="kw2">self</span><span class="br0">&#41;</span>:
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">self</span>.<span class="me1">tk</span> = Tk<span class="br0">&#40;</span><span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; frame = Frame<span class="br0">&#40;</span><span class="kw2">self</span>.<span class="me1">tk</span><span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; frame.<span class="me1">pack</span><span class="br0">&#40;</span><span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; Button<span class="br0">&#40;</span>frame, text=<span class="st0">&quot;Compute&quot;</span>, command=<span class="kw2">self</span>.<span class="me1">computeWithGUIAntifreeze</span><span class="br0">&#41;</span>.<span class="me1">pack</span><span class="br0">&#40;</span><span class="br0">&#41;</span>

&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">def</span> run<span class="br0">&#40;</span><span class="kw2">self</span><span class="br0">&#41;</span>:
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">self</span>.<span class="me1">tk</span>.<span class="me1">mainloop</span><span class="br0">&#40;</span><span class="br0">&#41;</span>

&nbsp; &nbsp; <span class="kw1">def</span> computeWithGUIAntifreeze<span class="br0">&#40;</span><span class="kw2">self</span><span class="br0">&#41;</span>:
&nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&quot;&quot;&quot; Метод-прокладка для запуска в новом потоке вычислений &quot;&quot;&quot;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">threading</span>.<span class="me1">Thread</span><span class="br0">&#40;</span>target=<span class="kw2">self</span>.<span class="me1">compute</span><span class="br0">&#41;</span>.<span class="me1">start</span><span class="br0">&#40;</span><span class="br0">&#41;</span>

&nbsp; &nbsp; <span class="kw1">def</span> compute<span class="br0">&#40;</span><span class="kw2">self</span><span class="br0">&#41;</span>:
&nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&quot;&quot;&quot;&quot; Тут как раз и происходят длительные вычисления &quot;&quot;&quot;</span><span class="st0">&quot;
&nbsp; &nbsp; &nbsp; &nbsp; time.sleep(15)

gui = AppGUI()
gui.run()</span></div>
</div>
</pre>
<p>2 &#8212; Использовать время от времени методы:</p>
<ul>
<li><strong>Tk.update()</strong>;</li>
<li><strong>Tk.update_idletasks()</strong> &#8212; только обновляет окна, но не вызывает обработку событий, сгенерированных пользователем, в отличие от Tk.update();</li>
</ul>
<p>Использовать эти методы стоит с осторожностью, дабы не возникло неприятных ситуаций (подробнее в документации). Таково предостережение официальной документации.</p>
<p>Ссылки к посту:<br />
<a href="http://www.tcl.tk/man/tcl8.5/TclCmd/update.htm">http://www.tcl.tk/man/tcl8.5/TclCmd/update.htm</a> &#8212; официальная документация по Tcl/Tk.</p>
]]></content:encoded>
			<wfw:commentRss>http://zetblog.ru/programming/200910/python-tkinter-antifreeze/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Python: генератор списка паролей для перебора (brute-force).</title>
		<link>http://zetblog.ru/programming/200910/python-passwords-list-for-bruteforce/</link>
		<comments>http://zetblog.ru/programming/200910/python-passwords-list-for-bruteforce/#comments</comments>
		<pubDate>Tue, 13 Oct 2009 11:56:19 +0000</pubDate>
		<dc:creator>lizz</dc:creator>
				<category><![CDATA[прикладное]]></category>
		<category><![CDATA[Программирование]]></category>
		<category><![CDATA[Brute Force]]></category>
		<category><![CDATA[Python]]></category>

		<guid isPermaLink="false">http://zetblog.ru/?p=716</guid>
		<description><![CDATA[При написании в очередной раз программы для подбора паролей к чему-либо (исключительно в образовательных целях и для учёбы ;-) ) опять возникла необходимость в итераторе по заданному алфавиту. Т.е. необходимо написать класс, который мог бы генерировать пароли для последующей передачи их в программу, которая &#171;примеряла&#187; их к чему-надо. К чему &#8212; дело третье и сейчас [...]]]></description>
			<content:encoded><![CDATA[<p>При написании в очередной раз программы для подбора паролей к чему-либо (исключительно в образовательных целях и для учёбы ;-) ) опять возникла необходимость в итераторе по заданному алфавиту. Т.е. необходимо написать класс, который мог бы генерировать пароли для последующей передачи их в программу, которая &#171;примеряла&#187; их к чему-надо. К чему &#8212; дело третье и сейчас нас (вернее Вас) не волнует. В результате получился скромный класс, который приведён ниже со столь же скромными моими комментариями к нему :-).<br />
<span id="more-716"></span></p>
<p>Сам класс для перебора паролей ко всему и вся таков:</p>
<pre class="brush: python"># -*- coding: utf-8 -*-

EN = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
en = "abcdefghijklmnopqrstuvwxyz"
RU = "АБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯ"
ru = "абвгдеёжзийклмнопрстуфхцчшщъыьэюя"
digits = "1234567890"
space = " "
p = ",.-!?;:'\"/()"
op = "+-*/:^()&lt;&gt;="
all_spec = "`~!@#$%^&amp;*-_=+\\|/?.&gt;,&lt; '\";:[]{}"

class ABCIterator:
    firstuse_flag = True
    stop = None

    def __init__(self, start="", stop=None, start_len=None, stop_len=None, abc=en+EN+digits+all_spec):
        assert len(abc) &gt; 0
        if start_len is not None:
            assert start_len &gt; 0
            #assert start == ""
            self.current_str = list(abc[0]*start_len)
        else:
            self.current_str = list(filter(lambda x: x in abc, start))
        if stop_len is not None:
            assert (start_len is None) or (start_len &lt;= stop_len)
            assert stop_len &gt; 0
            self.stop = list(abc[0]*(stop_len+1)) # т.к. итератор работает с полуотрезками
        else:
            if stop is not None: self.stop = list(filter(lambda x: x in abc, stop))
        self.abc = list(abc)

    def __iter__(self):
        return self

    def next(self):
        if (self.stop is not None) and (self.stop == self.current_str):
            raise StopIteration
        if self.current_str == []:
            self.current_str.append(self.abc[0])
            self.firstuse_flag = False
            return self.abc[0]
        elif self.firstuse_flag:
            self.firstuse_flag = False
            return "".join(self.current_str)
        offset = 0
        while offset &lt; len(self.current_str):
            if self.current_str[offset] != self.abc[-1]:
                self.current_str[offset] = self.abc[self.abc.index(self.current_str[offset])+1]
                # выпендрёшь для полуотрезка
                if (self.stop is not None) and (self.current_str == self.stop):
                    raise StopIteration
                return "".join(self.current_str)
            self.current_str[offset] = self.abc[0]
            offset += 1
        self.current_str = [self.abc[0]] + self.current_str
        # опять же оно же
        if (self.stop is not None) and (self.current_str == self.stop):
            raise StopIteration
        return "".join(self.current_str)
</pre>
<p>А таковы мои пояснения к нему:</p>
<ul>
<li><strong>firstuse_flag</strong> &#8212; свойство, которое указывает на то, что итератор используется впервые и не стоит производить итерацию, надо лишь вернуть текущее значени строки. Это нужно для того, чтобы в цикле не &#171;съедалось&#187; первое значение (напр., инициализировали итератор с начальной строкой &#171;aaa&#187;, а при 1й же итерации он вернул бы, без этого чудесного свойства, &#171;baa&#187;)</li>
<li><strong>stop</strong> &#8212; указывает на значение, на котором пора бы уже остановиться и вызвать исключение StopIteration. Если не задано (имеет значение None), то не пора, итератор будет бесконечным</li>
<li><strong>__init__(start=&#187;, stop=None, start_len=None, stop_len=None, abc=en+EN+digits+all_spec, **kwargs)</strong> &#8212; в общем то сам конструктор. <strong>start</strong> &#8212; начальное значение, <strong>stop</strong> &#8212; конечное, если не задано или идёт до начального, то итерации происходят бесконечно. Можно так же задать начальную и конечную длину, место конкретных значений с помощью <strong>start_len</strong> и <strong>stop_len</strong>. Если задана длина и начальные значения, то приоритет будет иметь длина, что можно легко исправить, если для кого-то это критично. <strong>abc</strong> &#8212; алфавит, над которым будут производиться итерации.</li>
<li><strong>__iter__()</strong> &#8212; необходимо для того чтобы класс был полноценным итератором.</li>
<li><strong>next()</strong> &#8212; возвращает следующую строку, в общем-то этот метод так же необходим для того чтобы класс был итератором.</li>
</ul>
<p>Пример использования:</p>
<pre>
<div class="codesnip-container" >
<div class="python codesnip" style="font-family:monospace;"><span class="sy0">&gt;&gt;&gt;</span> <span class="kw1">for</span> i <span class="kw1">in</span> ABCIterator<span class="br0">&#40;</span>start_len=<span class="nu0">1</span>, stop_len=<span class="nu0">3</span>, abc=<span class="st0">&quot;abc&quot;</span><span class="br0">&#41;</span>:
... &nbsp; &nbsp; <span class="me1">i</span>
...
<span class="st0">'a'</span>
<span class="st0">'b'</span>
<span class="br0">&#91;</span>...<span class="br0">&#93;</span>
<span class="st0">'bcc'</span>
<span class="st0">'ccc'</span>
<span class="sy0">&gt;&gt;&gt;</span></div>
</div>
</pre>
<p>Ну, как-то так оно и работает. Если кому-то что-то непонятно, то могу объяснить подробнее. В общем как обычно, всё в комменты ;-). Неплохо было бы ещё реализовать преобразование чисел в строки и наоборот, но это позже&#8230; может быть.</p>
]]></content:encoded>
			<wfw:commentRss>http://zetblog.ru/programming/200910/python-passwords-list-for-bruteforce/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>Python: файловый интерпретатор.</title>
		<link>http://zetblog.ru/programming/200905/python-%d1%84%d0%b0%d0%b9%d0%bb%d0%be%d0%b2%d1%8b%d0%b9-%d0%b8%d0%bd%d1%82%d0%b5%d1%80%d0%bf%d1%80%d0%b5%d1%82%d0%b0%d1%82%d0%be%d1%80/</link>
		<comments>http://zetblog.ru/programming/200905/python-%d1%84%d0%b0%d0%b9%d0%bb%d0%be%d0%b2%d1%8b%d0%b9-%d0%b8%d0%bd%d1%82%d0%b5%d1%80%d0%bf%d1%80%d0%b5%d1%82%d0%b0%d1%82%d0%be%d1%80/#comments</comments>
		<pubDate>Wed, 20 May 2009 12:46:23 +0000</pubDate>
		<dc:creator>lizz</dc:creator>
				<category><![CDATA[Программирование]]></category>
		<category><![CDATA[Python]]></category>

		<guid isPermaLink="false">http://zetblog.ru/?p=710</guid>
		<description><![CDATA[Очередной бестолковый велосипед от СГУ. Требуется написать &#171;интерпретатор&#187;, который умел бы работать с файлами. Так же умел бы исполнять сторонние скрипты. Работа с файлами заключается в следующих функциях &#8212; открыть на запись, открыть на чтение, закрыть файл, читать из файла, читать n байт, записать в файл, читать в буфер, записать из буфера в файл, сместиться [...]]]></description>
			<content:encoded><![CDATA[<p>Очередной бестолковый велосипед от СГУ. Требуется написать &#171;интерпретатор&#187;, который умел бы работать с файлами. Так же умел бы исполнять сторонние скрипты. Работа с файлами заключается в следующих функциях &#8212; открыть на запись, открыть на чтение, закрыть файл, читать из файла, читать n байт, записать в файл, читать в буфер, записать из буфера в файл, сместиться на определённую позицию.<br />
<span id="more-710"></span></p>
<p>По сути получается некая прослойка между консолью и функциями самого языка программирования. В C++ пришлось наверное помучиться над этим (хотя ничего сложного, главное &#8212; знания), в python&#8217;е всё как всегда ;-).</p>
<div class="codesnip-container" >
<div class="python codesnip" style="font-family:monospace;"><span class="co1">#!/usr/bin/env python</span><br />
<span class="co1"># -*- coding: utf-8 -*-</span></p>
<p><span class="kw1">import</span> <span class="kw3">sys</span></p>
<p><span class="kw1">class</span> MyFile:<br />
<span class="kw1">def</span> <span class="kw4">__init__</span><span class="br0">&#40;</span><span class="kw2">self</span><span class="br0">&#41;</span>:<br />
<span class="kw2">self</span>.<span class="me1">name</span> = <span class="kw2">None</span><br />
<span class="kw2">self</span>.<span class="me1">desc</span> = <span class="kw2">None</span><br />
<span class="kw2">self</span>.<span class="me1">flags</span> = <span class="kw2">None</span><br />
<span class="kw2">self</span>.<span class="me1">buffer</span> = <span class="st0">&quot;&quot;</span></p>
<p><span class="kw1">def</span> <span class="kw2">open</span><span class="br0">&#40;</span><span class="kw2">self</span>, fname, flags<span class="br0">&#41;</span>:<br />
<span class="kw1">print</span> <span class="st0">&quot;Opening %s in mode %s.&quot;</span> <span class="sy0">%</span> <span class="br0">&#40;</span>fname, flags<span class="br0">&#41;</span><br />
<span class="kw2">self</span>.<span class="me1">name</span> = fname<br />
<span class="kw2">self</span>.<span class="me1">flags</span> = flags<br />
<span class="kw2">self</span>.<span class="me1">desc</span> = <span class="kw2">open</span><span class="br0">&#40;</span><span class="kw2">self</span>.<span class="me1">name</span>, flags<span class="br0">&#41;</span></p>
<p><span class="kw1">def</span> write<span class="br0">&#40;</span><span class="kw2">self</span>, data<span class="br0">&#41;</span>:<br />
<span class="kw1">print</span> <span class="st0">&quot;Writing data in file.&quot;</span><br />
<span class="kw2">self</span>.<span class="me1">desc</span>.<span class="me1">write</span><span class="br0">&#40;</span>data<span class="br0">&#41;</span></p>
<p><span class="kw1">def</span> writeFromBuffer<span class="br0">&#40;</span><span class="kw2">self</span>, <span class="kw3">bytes</span>=<span class="kw2">None</span><span class="br0">&#41;</span>:<br />
<span class="kw1">if</span> <span class="kw3">bytes</span> <span class="kw1">is</span> <span class="kw2">None</span>:<br />
<span class="kw3">bytes</span> = <span class="kw2">len</span><span class="br0">&#40;</span><span class="kw2">self</span>.<span class="me1">buffer</span><span class="br0">&#41;</span><br />
<span class="kw1">print</span> <span class="st0">&quot;Writing data in file from buffer.&quot;</span><br />
<span class="kw2">self</span>.<span class="me1">desc</span>.<span class="me1">write</span><span class="br0">&#40;</span><span class="kw2">self</span>.<span class="me1">buffer</span><span class="br0">&#91;</span>:<span class="kw3">bytes</span><span class="br0">&#93;</span><span class="br0">&#41;</span><br />
<span class="kw1">print</span> <span class="st0">&quot;Wrote %d bytes.&quot;</span> <span class="sy0">%</span> <span class="kw2">len</span><span class="br0">&#40;</span><span class="kw2">self</span>.<span class="me1">buffer</span><span class="br0">&#91;</span>:<span class="kw3">bytes</span><span class="br0">&#93;</span><span class="br0">&#41;</span><br />
<span class="kw2">self</span>.<span class="me1">buffer</span> = <span class="kw2">self</span>.<span class="me1">buffer</span><span class="br0">&#91;</span><span class="kw3">bytes</span>:<span class="br0">&#93;</span><span class="br0">&#41;</span></p>
<p><span class="kw1">def</span> read<span class="br0">&#40;</span><span class="kw2">self</span>, <span class="kw3">bytes</span>=<span class="kw2">None</span><span class="br0">&#41;</span>:<br />
<span class="kw1">print</span> <span class="st0">&quot;Reading from file.&quot;</span><br />
<span class="kw1">if</span> <span class="kw3">bytes</span> <span class="kw1">is</span> <span class="kw2">None</span>:<br />
r = <span class="kw2">self</span>.<span class="me1">desc</span>.<span class="me1">read</span><span class="br0">&#40;</span><span class="br0">&#41;</span><br />
<span class="kw1">else</span>:<br />
r = <span class="kw2">self</span>.<span class="me1">desc</span>.<span class="me1">read</span><span class="br0">&#40;</span><span class="kw3">bytes</span><span class="br0">&#41;</span><br />
lr = <span class="kw2">len</span><span class="br0">&#40;</span>r<span class="br0">&#41;</span><br />
<span class="kw1">print</span> <span class="st0">&quot;Read %d bytes from file: <span class="es0">\&quot;</span>%s<span class="es0">\&quot;</span>.&quot;</span> <span class="sy0">%</span> <span class="br0">&#40;</span>lr, r<span class="br0">&#41;</span><br />
<span class="kw1">return</span> r</p>
<p><span class="kw1">def</span> writeToBuffer<span class="br0">&#40;</span><span class="kw2">self</span>, <span class="kw3">bytes</span>=<span class="kw2">None</span><span class="br0">&#41;</span>:<br />
<span class="kw1">print</span> <span class="st0">&quot;Reading from file to buffer.&quot;</span><br />
<span class="kw1">if</span> <span class="kw3">bytes</span> <span class="kw1">is</span> <span class="kw2">None</span>:<br />
r = <span class="kw2">self</span>.<span class="me1">desc</span>.<span class="me1">read</span><span class="br0">&#40;</span><span class="br0">&#41;</span><br />
<span class="kw1">else</span>:<br />
r = <span class="kw2">self</span>.<span class="me1">desc</span>.<span class="me1">read</span><span class="br0">&#40;</span><span class="kw3">bytes</span><span class="br0">&#41;</span><br />
lr = <span class="kw2">len</span><span class="br0">&#40;</span>r<span class="br0">&#41;</span><br />
<span class="kw2">self</span>.<span class="me1">buffer</span> += r<br />
<span class="kw1">print</span> <span class="st0">&quot;Read %d bytes from file: <span class="es0">\&quot;</span>%s<span class="es0">\&quot;</span>.&quot;</span> <span class="sy0">%</span> <span class="br0">&#40;</span>lr, r<span class="br0">&#41;</span><br />
<span class="kw1">return</span> r</p>
<p><span class="kw1">def</span> clearBuffer<span class="br0">&#40;</span><span class="kw2">self</span><span class="br0">&#41;</span>:<br />
<span class="kw2">self</span>.<span class="me1">buffer</span> = <span class="st0">&quot;&quot;</span></p>
<p><span class="kw1">def</span> close<span class="br0">&#40;</span><span class="kw2">self</span><span class="br0">&#41;</span>:<br />
<span class="kw1">print</span> <span class="st0">&quot;Closing file.&quot;</span><br />
<span class="kw2">self</span>.<span class="me1">desc</span>.<span class="me1">close</span><span class="br0">&#40;</span><span class="br0">&#41;</span></p>
<p><span class="kw1">def</span> seek<span class="br0">&#40;</span><span class="kw2">self</span>, position<span class="br0">&#41;</span>:<br />
position = <span class="kw2">int</span><span class="br0">&#40;</span>position<span class="br0">&#41;</span><br />
<span class="kw1">print</span> <span class="st0">&quot;Seting seek in file to position %d&quot;</span> <span class="sy0">%</span> position<br />
<span class="kw2">self</span>.<span class="me1">desc</span>.<span class="me1">seek</span><span class="br0">&#40;</span>position<span class="br0">&#41;</span></p>
<p><span class="kw1">def</span> process<span class="br0">&#40;</span>f<span class="br0">&#41;</span>:<br />
f = <span class="kw2">open</span><span class="br0">&#40;</span>f, <span class="st0">&quot;rb&quot;</span><span class="br0">&#41;</span><br />
mf = MyFile<span class="br0">&#40;</span><span class="br0">&#41;</span><br />
<span class="kw1">for</span> line <span class="kw1">in</span> f:<br />
<span class="kw2">eval</span><span class="br0">&#40;</span><span class="st0">&quot;mf.&quot;</span> + line<span class="br0">&#41;</span><br />
f.<span class="me1">close</span><span class="br0">&#40;</span><span class="br0">&#41;</span></p>
<p><span class="kw1">if</span> __name__ == <span class="st0">&quot;__main__&quot;</span>:<br />
args = <span class="kw3">sys</span>.<span class="me1">argv</span><span class="br0">&#91;</span>1:<span class="br0">&#93;</span><br />
<span class="kw1">if</span> <span class="kw2">len</span><span class="br0">&#40;</span>args<span class="br0">&#41;</span> <span class="sy0">&amp;</span>gt<span class="sy0">;</span> 0:<br />
<span class="kw1">for</span> arg <span class="kw1">in</span> args:<br />
<span class="kw1">try</span>:<br />
process<span class="br0">&#40;</span>arg<span class="br0">&#41;</span><br />
<span class="kw1">print</span> <span class="st0">&quot;!!! %s processed successfully. !!!&quot;</span> <span class="sy0">%</span> arg<br />
<span class="kw1">except</span>:<br />
<span class="kw1">print</span> <span class="st0">&quot;!!! Error while processing script %s. !!!&quot;</span> <span class="sy0">%</span> arg<br />
<span class="kw1">else</span>:<br />
action = <span class="st0">&quot;&quot;</span><br />
<span class="kw1">print</span> <span class="st0">&quot;q &#8212; quit&quot;</span><br />
<span class="kw1">print</span> <span class="st0">&quot;open(fname) &#8212; open file&quot;</span><br />
<span class="kw1">print</span> <span class="st0">&quot;write(data) &#8212; write data in file&quot;</span><br />
<span class="kw1">print</span> <span class="st0">&quot;read([bytes]) &#8212; read data from file&quot;</span><br />
<span class="kw1">print</span> <span class="st0">&quot;seek(position) &#8212; set seek in file to position&quot;</span><br />
<span class="kw1">print</span> <span class="st0">&quot;close() &#8212; close file&quot;</span><br />
f = MyFile<span class="br0">&#40;</span><span class="br0">&#41;</span><br />
<span class="kw1">while</span> <span class="kw2">True</span>:<br />
<span class="kw1">try</span>:<br />
<span class="kw2">eval</span><span class="br0">&#40;</span><span class="st0">&quot;f.&quot;</span> + <span class="kw2">raw_input</span><span class="br0">&#40;</span><span class="st0">&quot;&amp;gt; &quot;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><br />
<span class="kw1">except</span>:<br />
<span class="kw1">print</span> <span class="st0">&quot;Error.&quot;</span><br />
<span class="kw1">else</span>:<br />
<span class="kw1">print</span> <span class="st0">&quot;Ok.&quot;</span></div>
</div>
<p>Если мы хотим работать в интерактивном режиме &#8212; то просто выполняем скрипт, если хотим обработать скрипты &#8212; передаём их имена в параметрах программы. Например:</p>
<div class="codesnip-container" >$./main.py 1.scr 2.scr 3.scr</div>
<p>На сегодня, пожалуй, хватит с меня постов, подожду пока эти оценят ;-).</p>
]]></content:encoded>
			<wfw:commentRss>http://zetblog.ru/programming/200905/python-%d1%84%d0%b0%d0%b9%d0%bb%d0%be%d0%b2%d1%8b%d0%b9-%d0%b8%d0%bd%d1%82%d0%b5%d1%80%d0%bf%d1%80%d0%b5%d1%82%d0%b0%d1%82%d0%be%d1%80/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Python: генерация группы ключей.</title>
		<link>http://zetblog.ru/programming/200905/python-%d0%b3%d0%b5%d0%bd%d0%b5%d1%80%d0%b0%d1%86%d0%b8%d1%8f-%d0%b3%d1%80%d1%83%d0%bf%d0%bf%d1%8b-%d0%ba%d0%bb%d1%8e%d1%87%d0%b5%d0%b9/</link>
		<comments>http://zetblog.ru/programming/200905/python-%d0%b3%d0%b5%d0%bd%d0%b5%d1%80%d0%b0%d1%86%d0%b8%d1%8f-%d0%b3%d1%80%d1%83%d0%bf%d0%bf%d1%8b-%d0%ba%d0%bb%d1%8e%d1%87%d0%b5%d0%b9/#comments</comments>
		<pubDate>Wed, 20 May 2009 12:23:34 +0000</pubDate>
		<dc:creator>lizz</dc:creator>
				<category><![CDATA[криптография]]></category>
		<category><![CDATA[Программирование]]></category>
		<category><![CDATA[Python]]></category>

		<guid isPermaLink="false">http://zetblog.ru/?p=707</guid>
		<description><![CDATA[Опять делюсь универскими наработками. Задача в общем то примитивная (или по крайней мере её реализация). Надо сгенерировать N равнозначных ключей для шифрования/дешифрования сообщения. Т.е., генерируем 10 ключей, шифруем сообщение любым из этих 10, расшифровываем так же любым из этих 10. Например, зашифровали пятым ключом, расшифровали третьим, или десятым. Для реализации поставленной задачи опять прибегнем к [...]]]></description>
			<content:encoded><![CDATA[<p>Опять делюсь универскими наработками. Задача в общем то примитивная (или по крайней мере её реализация). Надо сгенерировать N равнозначных ключей для шифрования/дешифрования сообщения. Т.е., генерируем 10 ключей, шифруем сообщение любым из этих 10, расшифровываем так же любым из этих 10. Например, зашифровали пятым ключом, расшифровали третьим, или десятым.<br />
<span id="more-707"></span></p>
<p>Для реализации поставленной задачи опять прибегнем к ксору aka XOR, исключающее или, почти <a href="/programming/200812/%D0%BA%D1%80%D0%B8%D0%BF%D1%82%D0%BE%D0%B3%D1%80%D0%B0%D1%84%D0%B8%D1%8F-%D1%88%D0%B8%D1%84%D1%80-%D0%B2%D0%B5%D1%80%D0%BD%D0%B0%D0%BC%D0%B0/">шифр Вернама</a>. Почти &#8212; потому что длина ключа у нас по сути не равна длине сообщения. Алгоритм будет таков:</p>
<ol>
<li>Дано начальное значение ikey. В общем то это и будет на самом деле ключ, который используется в шифровании и расшифровке, просто он будет &#171;спрятан&#187; в сгенерированных ключах.</li>
<li>Генерируем 10 случайных строк по длине равных ключу ikey.</li>
<li>Для каждой строки из предыдущего пункта выполняем: xor(A, ikey) + A. Полученные строки и будут нашими ключами.</li>
</ol>
<p>Теперь для шифрования нам необходимо предварительно обработать введёный ключ и извлечь из него ikey. Это можно сделать поксорив первую половину ключа со второй. И с помощью ikey уже шифровать или расшифровывать сообщение.</p>
<p>Реализацию ксора в python нашёл на просторах инета (выглядит довольно красиво, я пока так не умею :-)), остальное писал сам. Вот исходник:</p>
<div class="codesnip-container" >
<div class="python codesnip" style="font-family:monospace;"><span class="co1">#!/usr/bin/env python</span><br />
<span class="co1"># -*- coding: utf-8 -*-</span></p>
<p><span class="kw1">import</span> <span class="kw3">random</span>, <span class="kw3">itertools</span>, <span class="kw3">struct</span></p>
<p><span class="kw1">def</span> generate_strings<span class="br0">&#40;</span>ikey, q=10<span class="br0">&#41;</span>:<br />
keys = <span class="br0">&#123;</span><span class="br0">&#125;</span><br />
<span class="kw1">for</span> i <span class="kw1">in</span> <span class="kw2">range</span><span class="br0">&#40;</span>q<span class="br0">&#41;</span>:<br />
<span class="co1">#print &quot;%d.&quot; % i,</span><br />
keys<span class="br0">&#91;</span>i<span class="br0">&#93;</span> = <span class="st0">&quot;&quot;</span><br />
<span class="kw1">for</span> j <span class="kw1">in</span> <span class="kw2">range</span><span class="br0">&#40;</span><span class="kw2">len</span><span class="br0">&#40;</span>ikey<span class="br0">&#41;</span><span class="br0">&#41;</span>:<br />
<span class="co1">#keys[i] += hex(random.randint(0, 15))[2 : ]</span><br />
keys<span class="br0">&#91;</span>i<span class="br0">&#93;</span> += <span class="kw2">chr</span><span class="br0">&#40;</span><span class="kw3">random</span>.<span class="me1">randint</span><span class="br0">&#40;</span><span class="nu0">0</span>, <span class="nu0">255</span><span class="br0">&#41;</span><span class="br0">&#41;</span><br />
<span class="co1">#print keys[i]</span><br />
<span class="kw1">return</span> keys</p>
<p><span class="kw1">def</span> xor <span class="br0">&#40;</span>s, key<span class="br0">&#41;</span>:<br />
key = <span class="kw3">itertools</span>.<span class="me1">cycle</span><span class="br0">&#40;</span>key<span class="br0">&#41;</span><br />
<span class="kw1">return</span> <span class="st0">&#187;</span>.<span class="me1">join</span><span class="br0">&#40;</span><span class="kw2">chr</span><span class="br0">&#40;</span><span class="kw2">ord</span><span class="br0">&#40;</span>x<span class="br0">&#41;</span> ^ <span class="kw2">ord</span><span class="br0">&#40;</span>y<span class="br0">&#41;</span><span class="br0">&#41;</span> <span class="kw1">for</span> <span class="br0">&#40;</span>x,y<span class="br0">&#41;</span> <span class="kw1">in</span> <span class="kw3">itertools</span>.<span class="me1">izip</span><span class="br0">&#40;</span>s, key<span class="br0">&#41;</span><span class="br0">&#41;</span></p>
<p><span class="kw1">def</span> generate_keys<span class="br0">&#40;</span>ikey<span class="br0">&#41;</span>:<br />
keys = generate_strings<span class="br0">&#40;</span>ikey<span class="br0">&#41;</span><br />
<span class="kw1">for</span> i <span class="kw1">in</span> <span class="kw2">range</span><span class="br0">&#40;</span><span class="kw2">len</span><span class="br0">&#40;</span>keys<span class="br0">&#41;</span><span class="br0">&#41;</span>:<br />
keys<span class="br0">&#91;</span>i<span class="br0">&#93;</span> = xor<span class="br0">&#40;</span>keys<span class="br0">&#91;</span>i<span class="br0">&#93;</span>, ikey<span class="br0">&#41;</span> + keys<span class="br0">&#91;</span>i<span class="br0">&#93;</span> <span class="co1">#xor(keys[i], b) + b</span><br />
<span class="kw1">return</span> keys</p>
<p><span class="kw1">def</span> bs2s<span class="br0">&#40;</span>bs<span class="br0">&#41;</span>:<br />
ss = <span class="st0">&quot;&quot;</span><br />
<span class="kw1">for</span> i <span class="kw1">in</span> bs:<br />
s = <span class="kw2">hex</span><span class="br0">&#40;</span><span class="kw2">ord</span><span class="br0">&#40;</span>i<span class="br0">&#41;</span><span class="br0">&#41;</span><span class="br0">&#91;</span>2 : <span class="br0">&#93;</span><br />
<span class="kw1">if</span> <span class="kw2">len</span><span class="br0">&#40;</span>s<span class="br0">&#41;</span> == <span class="nu0">1</span>:<br />
ss += <span class="st0">&quot;0&quot;</span><br />
ss += s<br />
<span class="kw1">return</span> ss</p>
<p><span class="kw1">def</span> s2bs<span class="br0">&#40;</span>ss<span class="br0">&#41;</span>:<br />
bs = <span class="st0">&quot;&quot;</span><br />
<span class="kw1">for</span> i <span class="kw1">in</span> <span class="kw2">range</span><span class="br0">&#40;</span>0, <span class="kw2">len</span><span class="br0">&#40;</span>ss<span class="br0">&#41;</span>, 2<span class="br0">&#41;</span>:<br />
bs += <span class="kw2">chr</span><span class="br0">&#40;</span><span class="kw2">int</span><span class="br0">&#40;</span>ss<span class="br0">&#91;</span>i : i +2<span class="br0">&#93;</span>, 16<span class="br0">&#41;</span><span class="br0">&#41;</span><br />
<span class="kw1">return</span> bs</p>
<p><span class="kw1">def</span> restore_key<span class="br0">&#40;</span>key<span class="br0">&#41;</span>:<br />
c = <span class="kw2">len</span><span class="br0">&#40;</span>key<span class="br0">&#41;</span> / 2<br />
<span class="kw1">return</span> xor<span class="br0">&#40;</span>key<span class="br0">&#91;</span> : c<span class="br0">&#93;</span>, key<span class="br0">&#91;</span>c : <span class="br0">&#93;</span><span class="br0">&#41;</span></p>
<p><span class="kw1">if</span> __name__ == <span class="st0">&quot;__main__&quot;</span>:<br />
action = <span class="st0">&quot;&quot;</span><br />
<span class="kw1">print</span> <span class="st0">&quot;Select action:<span class="es0">\n</span>g &#8212; generate keys<span class="es0">\n</span>c &#8212; encrypt or decrypt file<span class="es0">\n</span>q &#8212; quit&quot;</span><br />
<span class="kw1">while</span> action <span class="sy0">!</span>= <span class="st0">&quot;q&quot;</span>:<br />
action = <span class="kw2">raw_input</span><span class="br0">&#40;</span><span class="st0">&quot;&amp;gt; &quot;</span><span class="br0">&#41;</span><br />
<span class="kw1">if</span> action == <span class="st0">&quot;g&quot;</span>:<br />
ikey = <span class="kw2">raw_input</span><span class="br0">&#40;</span><span class="st0">&quot;Enter initial key value: &quot;</span><span class="br0">&#41;</span><br />
keys = generate_keys<span class="br0">&#40;</span>ikey<span class="br0">&#41;</span><br />
<span class="kw1">print</span> <span class="st0">&quot;Generated keys:&quot;</span><br />
<span class="kw1">for</span> i <span class="kw1">in</span> <span class="kw2">range</span><span class="br0">&#40;</span><span class="kw2">len</span><span class="br0">&#40;</span>keys<span class="br0">&#41;</span><span class="br0">&#41;</span>:<br />
<span class="kw1">print</span> <span class="st0">&quot;%d. %s&quot;</span> <span class="sy0">%</span> <span class="br0">&#40;</span>i, bs2s<span class="br0">&#40;</span>keys<span class="br0">&#91;</span>i<span class="br0">&#93;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><br />
<span class="kw1">elif</span> action == <span class="st0">&quot;c&quot;</span>:<br />
f_in_name = <span class="kw2">raw_input</span><span class="br0">&#40;</span><span class="st0">&quot;Enter input file name: &quot;</span><span class="br0">&#41;</span><br />
f_out_name = <span class="kw2">raw_input</span><span class="br0">&#40;</span><span class="st0">&quot;Enter output file name: &quot;</span><span class="br0">&#41;</span><br />
key = <span class="kw2">raw_input</span><span class="br0">&#40;</span><span class="st0">&quot;Enter key: &quot;</span><span class="br0">&#41;</span><br />
<span class="kw1">try</span>:<br />
key = restore_key<span class="br0">&#40;</span>s2bs<span class="br0">&#40;</span>key<span class="br0">&#41;</span><span class="br0">&#41;</span><br />
f = <span class="kw2">open</span><span class="br0">&#40;</span>f_in_name, <span class="st0">&quot;rb&quot;</span><span class="br0">&#41;</span><br />
c = xor<span class="br0">&#40;</span>f.<span class="me1">read</span><span class="br0">&#40;</span><span class="br0">&#41;</span>, key<span class="br0">&#41;</span><br />
f.<span class="me1">close</span><span class="br0">&#40;</span><span class="br0">&#41;</span><br />
f = <span class="kw2">open</span><span class="br0">&#40;</span>f_out_name, <span class="st0">&quot;wb&quot;</span><span class="br0">&#41;</span><br />
f.<span class="me1">write</span><span class="br0">&#40;</span>c<span class="br0">&#41;</span><br />
f.<span class="me1">close</span><span class="br0">&#40;</span><span class="br0">&#41;</span><br />
<span class="kw1">except</span>:<br />
<span class="kw1">print</span> <span class="st0">&quot;Errors :-(.&quot;</span><br />
<span class="kw1">elif</span> action <span class="sy0">!</span>= <span class="st0">&quot;q&quot;</span>:<br />
<span class="kw1">print</span> <span class="st0">&quot;Invalid action.&quot;</span></div>
</div>
<p>Единственная поправка к алгоритму, который я описал &#8212; ключи перед выводом я перевожу в шестнадцатиричное число, чтобы не хранить ключи в бинарном виде, ну и после ввода так же перевожу обратно. На этом всё.</p>
<p>Ссылки к статье:<br />
<a href="http://code.activestate.com/recipes/496970/">http://code.activestate.com/recipes/496970/</a> &#8212; &#171;Recipe 496970: xor for strings&#187;.</p>
]]></content:encoded>
			<wfw:commentRss>http://zetblog.ru/programming/200905/python-%d0%b3%d0%b5%d0%bd%d0%b5%d1%80%d0%b0%d1%86%d0%b8%d1%8f-%d0%b3%d1%80%d1%83%d0%bf%d0%bf%d1%8b-%d0%ba%d0%bb%d1%8e%d1%87%d0%b5%d0%b9/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Python: Аналог интерактивного режима у себя в программе.</title>
		<link>http://zetblog.ru/programming/200903/%d0%b0%d0%bd%d0%b0%d0%bb%d0%be%d0%b3-%d0%b8%d0%bd%d1%82%d0%b5%d1%80%d0%b0%d0%ba%d1%82%d0%b8%d0%b2%d0%bd%d0%be%d0%b3%d0%be-%d1%80%d0%b5%d0%b6%d0%b8%d0%bc%d0%b0/</link>
		<comments>http://zetblog.ru/programming/200903/%d0%b0%d0%bd%d0%b0%d0%bb%d0%be%d0%b3-%d0%b8%d0%bd%d1%82%d0%b5%d1%80%d0%b0%d0%ba%d1%82%d0%b8%d0%b2%d0%bd%d0%be%d0%b3%d0%be-%d1%80%d0%b5%d0%b6%d0%b8%d0%bc%d0%b0/#comments</comments>
		<pubDate>Fri, 13 Mar 2009 17:01:19 +0000</pubDate>
		<dc:creator>lizz</dc:creator>
				<category><![CDATA[общие вопросы]]></category>
		<category><![CDATA[Программирование]]></category>
		<category><![CDATA[Python]]></category>

		<guid isPermaLink="false">http://zetblog.ru/?p=616</guid>
		<description><![CDATA[Как-то лень было писать для задачки интерфейс, а в универе требовали, и тут в мою голову пришла мысль, что не плохо было бы иметь что-то вроде аналога интерактивного режима интерпретатора python&#8217;а (лицезреть который Вы можете выполнив команду python или нажав в виндовской IDLE F5). Решение оказалось в одну строчку :). Есть в python&#8217;е (да и [...]]]></description>
			<content:encoded><![CDATA[<p>Как-то лень было писать для задачки интерфейс, а в универе требовали, и тут в мою голову пришла мысль, что не плохо было бы иметь что-то вроде аналога интерактивного режима интерпретатора python&#8217;а (лицезреть который Вы можете выполнив команду python или нажав в виндовской IDLE F5).<br />
<span id="more-616"></span></p>
<p>Решение оказалось в одну строчку :). Есть в python&#8217;е (да и не только в нём) такая функция с неприличным именем, как <strong>eval</strong>. Она пытается преобразовать полученное в качестве параметра выражение в некий результат. Например:</p>
<div class="codesnip-container" >&gt;&gt;&gt; eval(&#171;2 + 2&#8243;)<br />
4<br />
&gt;&gt;&gt; a = 4<br />
&gt;&gt;&gt; eval(&#171;a ** a&#187;)<br />
256</div>
<p>Как вы уже наверное догадались, при наличии такой функции задача сводится к тривиальной. В моей задачке был объект db, методы которого и надо было вызывать для демонстрации функций программы. Вот два варианта их вызова:</p>
<div class="codesnip-container" >
<div class="python codesnip" style="font-family:monospace;"><span class="kw1">while</span> <span class="kw2">True</span>:<br />
<span class="kw2">input</span><span class="br0">&#40;</span><span class="br0">&#41;</span></div>
</div>
<p>При исполнении программы вводим &#171;db.method1(params)&#187;. Функция <strong>input([prompt])</strong> эквивалентна вызову <strong>eval(raw_input([prompt]))</strong>. Чтобы не писать каждый раз &#171;db.&#187;, можно упростить ввод пользователя:</p>
<div class="codesnip-container" >
<div class="python codesnip" style="font-family:monospace;"><span class="kw1">while</span> <span class="kw2">True</span>:<br />
<span class="kw2">eval</span><span class="br0">&#40;</span><span class="st0">&quot;db.&quot;</span> + <span class="kw2">raw_input</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span></div>
</div>
<p>Теперь достаточно писать просто &#171;method1(params)&#187;.</p>
<p>Так же у функции eval есть ещё 2 необязательных параметра <strong>eval(expression[, globals[, locals]])</strong>, через них можно передавать устанавливать значения глобальных и локальных переменных. Официальная документация находится <a href="http://docs.python.org/library/functions.html#eval">тут</a>.</p>
<p>На этом закончим. Конечно, данный вариант не подойдёт для конечного пользователя, т.к. любой пользовательский ввод следует проверять на корректность, но для демонстрации программы в универе вполне сойдёт.</p>
]]></content:encoded>
			<wfw:commentRss>http://zetblog.ru/programming/200903/%d0%b0%d0%bd%d0%b0%d0%bb%d0%be%d0%b3-%d0%b8%d0%bd%d1%82%d0%b5%d1%80%d0%b0%d0%ba%d1%82%d0%b8%d0%b2%d0%bd%d0%be%d0%b3%d0%be-%d1%80%d0%b5%d0%b6%d0%b8%d0%bc%d0%b0/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Python: Аутентификация с помощью протокола S/KEY.</title>
		<link>http://zetblog.ru/programming/200902/python-%d0%bf%d1%80%d0%be%d1%82%d0%be%d0%ba%d0%be%d0%bb-skey/</link>
		<comments>http://zetblog.ru/programming/200902/python-%d0%bf%d1%80%d0%be%d1%82%d0%be%d0%ba%d0%be%d0%bb-skey/#comments</comments>
		<pubDate>Wed, 25 Feb 2009 14:55:38 +0000</pubDate>
		<dc:creator>lizz</dc:creator>
				<category><![CDATA[криптография]]></category>
		<category><![CDATA[Программирование]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[аутентификация]]></category>

		<guid isPermaLink="false">http://zetblog.ru/?p=567</guid>
		<description><![CDATA[Смотрю тут многие интересуются безопасностью, поэтому решил выложить с описанием свою реализацию протокола S/KEY ;-). В общем то задача тривиальная, на мой взгляд, но может кому-то понадобится, если зададут в универе. S/KEY был разработан для аутентификации на на unix-подобных ОС, в частности, на &#171;глупых&#187; терминалах или на публичных компьютерах с низким уровнем доверия, где использовать [...]]]></description>
			<content:encoded><![CDATA[<p>Смотрю тут многие интересуются безопасностью, поэтому решил выложить с описанием свою реализацию протокола S/KEY ;-). В общем то задача тривиальная, на мой взгляд, но может кому-то понадобится, если зададут в универе.</p>
<p>S/KEY был разработан для аутентификации на на unix-подобных ОС, в частности, на &#171;глупых&#187; терминалах или на публичных компьютерах с низким уровнем доверия, где использовать долгосрочные пароли нецелесообразно. Как-то так =).<br />
<span id="more-567"></span></p>
<p>Начнём с описания протокола. Сам протокол предназначен для аутентификации пользователей с использованием одноразовых паролей. Распишем всё по шагам:</p>
<ol>
<li>Для инициализации программы надо взять случайное число w, которое может быть задано как пользователем, так и компьютером. Если это число станет известным злоумышленнику, то протокол будет скомпроментирован.</li>
<li>H &#8212; односторонняя функция, но т.к. односторонних функций не существует (по крайней мере обычные смертные о них точно не знают ;-) ), то возьмём какую-нибудь функцию, которая претендует на роль односторонней. Говоря простым языком, H &#8212; хеш-функция. Возьмём и пременим её n раз. Сначала к w, потом к H(w), H(H(w)), &#8230;, H(&#8230;H(w)&#8230;).</li>
<li>Начальное секретное число w уничтожается, дабы не досталось вражине.</li>
<li>Выводим пользователю сгенерированные n-1 хешей, пользователь запоминает, или, если он не мнемоник, сохраняет их у себя в укромном месте.</li>
<li>Сохраняем на сервере ключ под номером n для данного пользователя, все остальные уничтожаем.</li>
</ol>
<p>Теперь при попытки войти пользователь передаёт своё имя и в качестве пароля последний ключ из своего списка (ключ, который был сгенерирован на шаге n-1). Сервер получает этот ключ, находит запись о ключе для данного имени пользователя, и сравнивает результат хеширования полученного пароля с найденым у себя в базе ключом, если результат операции совпадает с введённым паролем, то допускает пользователя к своему сверхсекретному сервису (для условности обозначим его xxx ;-) ). Но это ещё не всё, ведь протокол использует одноразовые пароли, поэтому на сервере при удачной попытке входа хранящееся значение ключа заменяется на полученное в начале от пользователя (т.е. праобраз хеша), а пользователь вычёркивает из своего списка последний ключ. Т.о., при первом входе пользователь передают ключ с номером n &#8212; 1, на сервере хранится ключ с номером n, при втором n &#8212; 2 и n &#8212; 1 соответственно, и т.д..</p>
<p>Достоинства протокола: даже если траффик между пользователем и сервером xxx будут прослушивать, то злоумышленник получит устаревший пароль, для него встанет задача нахождения праобраза хеша, что принято считать неосуществимым, т.е. данный протокол неуязвим к сниффингу паролей.</p>
<p>Недостатки: при перехвате начального секретного ключа w можно самому сгенерировать такую последовательность; пользователя придётся инициировать заново после того, как он &#171;израсходует&#187; все свои ключи.</p>
<p>А вот и обещанная реализация:</p>
<pre>
<div class="codesnip-container" >
<div class="python codesnip" style="font-family:monospace;"><span class="kw1">from</span> <span class="kw3">md5</span> <span class="kw1">import</span> <span class="kw3">md5</span>
<span class="kw1">import</span> <span class="kw3">sys</span>, <span class="kw3">os</span>

<span class="kw1">def</span> skey_register<span class="br0">&#40;</span><span class="br0">&#41;</span>:
&nbsp; &nbsp; name = <span class="kw2">raw_input</span><span class="br0">&#40;</span><span class="st0">&quot;Enter your name: &quot;</span><span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="kw1">if</span> <span class="kw3">os</span>.<span class="me1">path</span>.<span class="me1">exists</span><span class="br0">&#40;</span>name<span class="br0">&#41;</span>:
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">print</span> <span class="st0">&quot;Error, user always exists.&quot;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">sys</span>.<span class="me1">exit</span><span class="br0">&#40;</span>-1<span class="br0">&#41;</span>
&nbsp; &nbsp; r = <span class="kw2">raw_input</span><span class="br0">&#40;</span><span class="st0">&quot;Enter random sequence R: &quot;</span><span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="kw1">for</span> i <span class="kw1">in</span> <span class="kw2">range</span><span class="br0">&#40;</span>100<span class="br0">&#41;</span>:
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; r = <span class="kw3">md5</span><span class="br0">&#40;</span>r<span class="br0">&#41;</span>.<span class="me1">hexdigest</span><span class="br0">&#40;</span><span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">print</span> i, r
&nbsp; &nbsp; key = <span class="kw3">md5</span><span class="br0">&#40;</span>r<span class="br0">&#41;</span>.<span class="me1">hexdigest</span><span class="br0">&#40;</span><span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="kw1">try</span>:
&nbsp; &nbsp; &nbsp; &nbsp; f = <span class="kw2">open</span><span class="br0">&#40;</span>name, <span class="st0">&quot;w&quot;</span><span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="kw1">except</span>:
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">print</span> <span class="st0">&quot;Error, can't open file %s for write!&quot;</span> <span class="sy0">%</span> name
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">sys</span>.<span class="me1">exit</span><span class="br0">&#40;</span>-1<span class="br0">&#41;</span>
&nbsp; &nbsp; f.<span class="me1">write</span><span class="br0">&#40;</span>key<span class="br0">&#41;</span>
&nbsp; &nbsp; f.<span class="me1">close</span><span class="br0">&#40;</span><span class="br0">&#41;</span>

<span class="kw1">def</span> skey_login<span class="br0">&#40;</span><span class="br0">&#41;</span>:
&nbsp; &nbsp; name = <span class="kw2">raw_input</span><span class="br0">&#40;</span><span class="st0">&quot;Enter your name: &quot;</span><span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="kw1">try</span>:
&nbsp; &nbsp; &nbsp; &nbsp; f = <span class="kw2">open</span><span class="br0">&#40;</span>name, <span class="st0">&quot;r&quot;</span><span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="kw1">except</span>:
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">print</span> <span class="st0">&quot;Error, can't open file %s!&quot;</span> <span class="sy0">%</span> name
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">sys</span>.<span class="me1">exit</span><span class="br0">&#40;</span>-1<span class="br0">&#41;</span>
&nbsp; &nbsp; passwd = f.<span class="me1">read</span><span class="br0">&#40;</span><span class="br0">&#41;</span>
&nbsp; &nbsp; f.<span class="me1">close</span><span class="br0">&#40;</span><span class="br0">&#41;</span>
&nbsp; &nbsp; upasswd = <span class="kw2">raw_input</span><span class="br0">&#40;</span><span class="st0">&quot;Enter password: &quot;</span><span class="br0">&#41;</span>
&nbsp; &nbsp; new_upasswd = <span class="kw3">md5</span><span class="br0">&#40;</span>upasswd<span class="br0">&#41;</span>.<span class="me1">hexdigest</span><span class="br0">&#40;</span><span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="kw1">if</span> new_upasswd <span class="sy0">!</span>= passwd:
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">print</span> <span class="st0">&quot;Invalid password!&quot;</span>
&nbsp; &nbsp; <span class="kw1">else</span>:
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">print</span> <span class="st0">&quot;Login successful!&quot;</span>
&nbsp; &nbsp; &nbsp; &nbsp; f = <span class="kw2">open</span><span class="br0">&#40;</span>name, <span class="st0">&quot;w&quot;</span><span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; f.<span class="me1">write</span><span class="br0">&#40;</span>upasswd<span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; f.<span class="me1">close</span><span class="br0">&#40;</span><span class="br0">&#41;</span>

<span class="kw1">if</span> __name__ == <span class="st0">&quot;__main__&quot;</span>:
&nbsp; &nbsp; <span class="kw1">while</span> <span class="kw2">True</span>:
&nbsp; &nbsp; &nbsp; &nbsp; action = <span class="kw2">raw_input</span><span class="br0">&#40;</span><span class="st0">&quot;Enter action ((r)egister, (l)ogin or (q)uit): &quot;</span><span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> action == <span class="st0">&quot;r&quot;</span>:
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; skey_register<span class="br0">&#40;</span><span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">elif</span> action == <span class="st0">&quot;l&quot;</span>:
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; skey_login<span class="br0">&#40;</span><span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">elif</span> action == <span class="st0">&quot;q&quot;</span>:
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">sys</span>.<span class="me1">exit</span><span class="br0">&#40;</span><span class="nu0">0</span><span class="br0">&#41;</span></div>
</div>
</pre>
<p>На мой взгяд код достаточно примитивен, поэтому комментировать не буду, если у кого вопросы &#8212; на форум ;-). В качестве хеш-функции была выбрана md5.</p>
<p>Ссылки к статье:<br />
<a href="http://en.wikipedia.org/wiki/Skey">http://en.wikipedia.org/wiki/Skey</a> &#8212; Skey на английской википедии.</p>
]]></content:encoded>
			<wfw:commentRss>http://zetblog.ru/programming/200902/python-%d0%bf%d1%80%d0%be%d1%82%d0%be%d0%ba%d0%be%d0%bb-skey/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Python: Масштабирование и наложение водяных знаков на изображение.</title>
		<link>http://zetblog.ru/programming/200902/python-%d0%bc%d0%b0%d1%81%d1%88%d1%82%d0%b0%d0%b1%d0%b8%d1%80%d0%be%d0%b2%d0%b0%d0%bd%d0%b8%d0%b5-%d0%b8-%d0%bd%d0%b0%d0%bb%d0%be%d0%b6%d0%b5%d0%bd%d0%b8%d0%b5-%d0%b2%d0%be%d0%b4%d1%8f%d0%bd%d1%8b/</link>
		<comments>http://zetblog.ru/programming/200902/python-%d0%bc%d0%b0%d1%81%d1%88%d1%82%d0%b0%d0%b1%d0%b8%d1%80%d0%be%d0%b2%d0%b0%d0%bd%d0%b8%d0%b5-%d0%b8-%d0%bd%d0%b0%d0%bb%d0%be%d0%b6%d0%b5%d0%bd%d0%b8%d0%b5-%d0%b2%d0%be%d0%b4%d1%8f%d0%bd%d1%8b/#comments</comments>
		<pubDate>Sat, 07 Feb 2009 00:40:57 +0000</pubDate>
		<dc:creator>lizz</dc:creator>
				<category><![CDATA[прикладное]]></category>
		<category><![CDATA[Программирование]]></category>
		<category><![CDATA[PIL]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[графика]]></category>

		<guid isPermaLink="false">http://zetblog.ru/?p=517</guid>
		<description><![CDATA[В данной статье будут рассмотрены некоторые возможности PIL (Python Imaging Library), а именно &#8212; использование библиотеки для создания превьюшек и наложения одного изображения на другое. Всё это делается достаточно тривиально, если знать как, ну а те, кто не знает, могут читать дальше ;-). Начнём с функции масштабирования. import Image def create_thumbnails(img, size): thumbnails = [] [...]]]></description>
			<content:encoded><![CDATA[<p>В данной статье будут рассмотрены некоторые возможности PIL (Python Imaging Library), а именно &#8212; использование библиотеки для создания превьюшек и наложения одного изображения на другое. Всё это делается достаточно тривиально, если знать как, ну а те, кто не знает, могут читать дальше ;-).<br />
<span id="more-517"></span></p>
<p>Начнём с функции масштабирования.</p>
<pre class="brush: python">import Image

def create_thumbnails(img, size):
    thumbnails = []
    for s in size:
        if img.size[0] == img.size[1]:
                thumbnails.append(img.resize((s, s), Image.ANTIALIAS))
        elif img.size[0] > img.size[1]:
            ratio = float(img.size[0]) / s
            thumbnails.append(img.resize((s, int(img.size[1]/ratio)), Image.ANTIALIAS))
        else:
            ratio = float(img.size[1]) / s
            thumbnails.append(img.resize((int(img.size[0]/ratio), s), Image.ANTIALIAS))
    return thumbnails

if __name__ == "__main__":
    img = Image.open("1.jpg")
    thumbs = create_thumbnails(img, (1000, ))
    thumbs.extend(create_thumbnails(img, (500, 250, 100)))

    c = 0
    for t in thumbs:
        t.save("%dt.jpg" % c)
        c += 1
</pre>
<p><strong>UPD</strong>: Как оказалось, код выше &#8212; велосипед :). Всё делается проще. Вместо вычисления соотношений пишем просто img.thumbnail((100, 100), Image.ANTIALIAS), остально за Вас всё сделает питон&#8230; Эхх, никакой свободы мысли ;).</p>
<p>Функция Image.open(), как Вы догадались, открывает изображение для дальнейших манипуляций с ним. Наша функция принимает полученный в результате открытия объект и список размеров (поэтому, если мы передаём один размер, то надо указать в параметрах, например, (100, ), а не просто (100)), по которым потом и будем масштабировать. Масштабирование происходит по большей стороне с сохранением пропорций. Возваращает функция так же список полученных превьюшек.</p>
<p>img.resize() &#8212; вторым параметром указывается метод преобразования, с Image.ANTIALIAS получается наиболее лучший вариант, так же можно указать Image.NEAREST, Image.BILINEAR, Image.BICUBIC вместо ANTIALIAS, первым &#8212; список из ширины и высоты нового изображения.</p>
<p>Теперь перейдём к водяным знакам. Для начала создадим какой-нибудь рисунок или надпись с прозрачным фоном и сохраним в формате png &#8212; это и будет наш водяной знак. Можно накладывать его разным способами, мы реализуем клонирование с заданным интервалом. Итак, вот как это примерно будет выглядеть:</p>
<pre class="brush: python">import Image, ImageEnhance

def add_watermark(image, watermark, opacity=1, wm_interval=0):
    assert opacity >= 0 and opacity <= 1
    if opacity < 1:
        if watermark.mode != 'RGBA':
            self.watermark = watermark.convert('RGBA')
        else:
            watermark = watermark.copy()
        alpha = watermark.split()[3]
        alpha = ImageEnhance.Brightness(alpha).enhance(opacity)
        watermark.putalpha(alpha)

    layer = Image.new('RGBA', image.size, (0,0,0,0))
    for y in range(0, image.size[1], watermark.size[1]+wm_interval):
        for x in range(0, image.size[0], watermark.size[0]+wm_interval):
            layer.paste(watermark, (x, y))
    return Image.composite(layer,  image,  layer)

if __name__ == "__main__":
    img = Image.open("1.jpg")
    wm = Image.open("wm.png")
    add_watermark(img, wm, 0.5, 50).save("wm_1.jpg")
</pre>
<p>В этой функции мы уменьшаем прозрачность, если она задана меньше 1, затем создаём новую картинку layer размером с исходное изображение и добавляем на неё водяные знаки с заданным интервалом, наконец возвращаем изображение, полученное из исходной картинки и нашей новой - layer.</p>
<p>Ссылки к статье:<br />
<a href="http://code.activestate.com/recipes/362879/">http://code.activestate.com/recipes/362879/</a> - Watermark with PIL.<br />
<a href="http://www.daniweb.com/code/snippet396.html"></a> - Resize an image (Python).</p>
]]></content:encoded>
			<wfw:commentRss>http://zetblog.ru/programming/200902/python-%d0%bc%d0%b0%d1%81%d1%88%d1%82%d0%b0%d0%b1%d0%b8%d1%80%d0%be%d0%b2%d0%b0%d0%bd%d0%b8%d0%b5-%d0%b8-%d0%bd%d0%b0%d0%bb%d0%be%d0%b6%d0%b5%d0%bd%d0%b8%d0%b5-%d0%b2%d0%be%d0%b4%d1%8f%d0%bd%d1%8b/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>

