<?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>pamiętnik programisty &#187; Python</title>
	<atom:link href="http://piotr.doniec.eu/devlog/category/python/feed/" rel="self" type="application/rss+xml" />
	<link>http://piotr.doniec.eu/devlog</link>
	<description></description>
	<lastBuildDate>Wed, 28 Dec 2011 23:52:24 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.2.1</generator>
		<item>
		<title>VIM, spacje zamiast wcięć</title>
		<link>http://piotr.doniec.eu/devlog/2010/07/vim-spacje-zamiast-wciec/</link>
		<comments>http://piotr.doniec.eu/devlog/2010/07/vim-spacje-zamiast-wciec/#comments</comments>
		<pubDate>Wed, 07 Jul 2010 21:14:03 +0000</pubDate>
		<dc:creator>pejotr</dc:creator>
				<category><![CDATA[Programowanie]]></category>
		<category><![CDATA[Python]]></category>

		<guid isPermaLink="false">http://piotr.doniec.eu/devlog/?p=511</guid>
		<description><![CDATA[Charakterystyczną cechą języka Python jest oddzielanie bloków kodu za pomocą wcięć. Z tego powodu są one niezmiernie istotne, a szukanie błędu powstałego przez źle umieszczone wcięcie, jeśli nie jest sygnalizowane przez interpreter może być bardzo czasochłonne a czasami wręcz frustrujące. Jakiś czas temu spotkałem się z takim problemem, który wynikł z używania 2 edytorów na [...]]]></description>
			<content:encoded><![CDATA[<p>Charakterystyczną cechą języka Python jest oddzielanie bloków kodu za pomocą wcięć. Z tego powodu są one niezmiernie istotne, a szukanie błędu powstałego przez źle umieszczone wcięcie, jeśli nie jest sygnalizowane przez interpreter może być bardzo czasochłonne a czasami wręcz frustrujące. Jakiś czas temu spotkałem się z takim problemem, który wynikł z używania 2 edytorów na 2 różnych maszynach. Na Windows korzystałem zamiennie z Vim oraz Programmers Notepad (tab = 4 spacje), pod linuxem wyłącznie z Vim bo tylko na tyle pozwalał interface konsolowy.<br />
W pewnym momencie doszło do kolizji. Z jakiegoś powodu część wcięć przesunęła się w lewo &#8211; czyli znikły. Na całe szczęście 90% błędów zostało wykrytych przez interpreter. Od razu zaznaczam że nie przeprowadziłem pełnej analizy problemu, ale coś mi podpowiadało że to wina Tab w Vim. Poniżej przedstawiam w jaki sposób zamieniać wszystkie tabulacje na 4 spacje. Komendy można umieścić w .vimrc (linux) czy też w _vimrc jeśli korzystamy z Windows:</p>
<pre class="brush: python">
set tabstop=4
set shiftwidth=4
set expandtab
</pre>
<p>Na sam koniec warto dodać, że mimo iż Vim może być postrzegany jako stary edytor, trudny w użyciu a posługują się nim tylko starzy wyjadacze-programiści z poprzedniej epoki, to ma on wiele funkcji których nie oferuje nawet Notepad++, a programowanie bez odrywania rąk od klawiatury jest o wiele mniej męczące. Polecam cheatsheet: http://www.qitty.net/lnx/vim-cheatsheet.png</p>
]]></content:encoded>
			<wfw:commentRss>http://piotr.doniec.eu/devlog/2010/07/vim-spacje-zamiast-wciec/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Scons &#8211; alternatywa dla Make, Qmake i podobnych</title>
		<link>http://piotr.doniec.eu/devlog/2010/01/scons-alternatywa-dla-make-qmake-i-podobnych/</link>
		<comments>http://piotr.doniec.eu/devlog/2010/01/scons-alternatywa-dla-make-qmake-i-podobnych/#comments</comments>
		<pubDate>Fri, 29 Jan 2010 12:35:20 +0000</pubDate>
		<dc:creator>pejotr</dc:creator>
				<category><![CDATA[C++]]></category>
		<category><![CDATA[Inne]]></category>
		<category><![CDATA[Programowanie]]></category>
		<category><![CDATA[Python]]></category>

		<guid isPermaLink="false">http://piotr.doniec.eu/devlog/?p=404</guid>
		<description><![CDATA[Scons jest oprogramowaniem którego zadaniem jest ułatwienie budowania binarnej wersji napisanego kodu. Twórcy zachwalają swoje dzieło jako między platformowe, łatwiejsze w użyciu i szybsze. Bazuje na Pythonie i dlatego postanowiłem się nim trochę zainteresować. Pierwsze próby zakończyłem sukcesem. Co mi się bardzo spodobało to możliwość wyboru kompilatora. Mając do dyspozycji g++ z MinGW oraz Visual [...]]]></description>
			<content:encoded><![CDATA[<p>Scons jest oprogramowaniem którego zadaniem jest ułatwienie budowania binarnej wersji napisanego kodu. Twórcy zachwalają swoje dzieło jako między platformowe, łatwiejsze w użyciu i szybsze. Bazuje na Pythonie i dlatego postanowiłem się nim trochę zainteresować.<br />
Pierwsze próby zakończyłem sukcesem. Co mi się bardzo spodobało to możliwość wyboru kompilatora. Mając do dyspozycji g++ z MinGW oraz Visual C++ Compiler, można zadecydować który z nich ma zostać użyty.<br />
Najprostszy plik z instrukcją zdudowania programu to 1 linia:</p>
<pre class="brush: python">
Program(&#039;main.cpp&#039;)
</pre>
<p>Na Windows domyślnie zostanie wykorzystany (o ile dostępny) kompilator Microsoftu. Jeśli jednak chcemy użyć g++, wystarczy dopisać jeszcze jedną linię:</p>
<pre class="brush: python">
env = Environment(tools = [&#039;mingw&#039;], CC = &#039;gcc&#039;, CCFLAGS = &#039;-O2&#039;)
env.Program(&#039;main.cpp&#039;)
</pre>
<p>Piewsze lody przełamane, kolejne próby będą sprawdzały łatwość dołączania zewnętrzych bibliotek jak boost czy qt.</p>
]]></content:encoded>
			<wfw:commentRss>http://piotr.doniec.eu/devlog/2010/01/scons-alternatywa-dla-make-qmake-i-podobnych/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>SOAP w Pythonie</title>
		<link>http://piotr.doniec.eu/devlog/2010/01/soap-w-pythonie/</link>
		<comments>http://piotr.doniec.eu/devlog/2010/01/soap-w-pythonie/#comments</comments>
		<pubDate>Mon, 11 Jan 2010 15:13:44 +0000</pubDate>
		<dc:creator>pejotr</dc:creator>
				<category><![CDATA[Programowanie]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[soap]]></category>
		<category><![CDATA[tricky]]></category>
		<category><![CDATA[webservices]]></category>

		<guid isPermaLink="false">http://piotr.doniec.eu/devlog/?p=396</guid>
		<description><![CDATA[Mimo że sam język jest uważany za potężny z dostępną dużą ilością bibliotek, to nie do koońca jest to prawda. SOAP w Pythonie niestety ale po prostu leży. Są 2 biblioteki umożliwiające tworzenie webserviców i tak naprawdę 2 które umożliwiają korzystanie z już utworzonych. Ja swoje próby rozpocząłem od soaplib, biblioteki która została porzucona przez [...]]]></description>
			<content:encoded><![CDATA[<p><img class="alignleft size-medium wp-image-400" title="soap_python" src="http://piotr.doniec.eu/devlog/wp-content/uploads/2010/01/soap_python-300x227.jpg" alt="soap_python" width="210" height="159" />Mimo że sam język jest uważany za potężny z dostępną dużą ilością bibliotek, to nie do koońca jest to prawda. SOAP w Pythonie niestety ale po prostu leży. Są 2 biblioteki umożliwiające tworzenie webserviców i tak naprawdę 2 które umożliwiają korzystanie z już utworzonych. Ja swoje próby rozpocząłem od soaplib, biblioteki która została porzucona przez twórców, ale w wyniku tzw. forków w miarę często pojawiają się nowe wersje. Niestety był to błąd.<br />
<span id="more-396"></span><br />
Nowe wersje od niezależnych twórców charakteryzują się większą bądź mniejszą ilością błędów. Najlepszą wersją okazała się wersja <strong>cuker soaplib</strong>, nie spełniała tylko 1 wymogu &#8211; generowania jakiegokolwiek kodu na podstawie WSDL. Jest to pewne nadużycie z mojej strony, biblioteka dostarczyła skrypt o nazwie wsdl2py, ale potrafił on poprawnie sparsować i zinterpretować plik wsdl utworzony tylko przez soaplib, co trzeba przyznać jest lekką &#8222;kichą&#8221;. Szkoda, biblioteka aktywnie rozwijana, wiązałem z nią spore nadzieje &#8211; odpadła.<br />
<strong>Suds</strong> to druga biblioteka związana z SOAP, aktywnie rozwijana, chwalona za łatwość korzystania, niestety przykłady dotyczą tylko tworzenia klinetów, serwerów poprostu tworzyć się nie da? W połączeniu z soaplib mogł by to być całkiem ciekawy duet.<br />
Biblioteka webserwisów dla Pythona <strong>ZSI</strong>,  w założeniu ma umożliwiać tworzenie i korzystanie z różnych webserviców, niestety projekt został porzucony w 2007 roku. Ale mimo to miłe zaskoczenie, dostarczane skrypty wsdl2py i wsdl2dispatch bez problemu radzą sobie z przykładowy wsdl dostępnymi w internecie. Tworzone są 3 pliki które potem można wykorzystać do implementacji serwera i klienta. Jednakże żeby nie było zbyt miło, serwer dostarczony z biblioteką jest jedno wątkowy. Jeśli operacje obsługi żądania jednego klienta są czasochłonne, to na ten czas serwer nie odpowiada na żądania innych klientów. Fatalna sprawa, ale! światełko w tunelu, ZSI można połączyć z Apache&#8217;m poprzez wykorzystanie mod_python ( oczywiście nie mogło być wersji dla python 2.6, na szczęście VS poradziło sobie z kompilacją ). Kolejna ślepa uliczka &#8211; jak bym tworzył stronę WWW. Przychodzi żądanie tworzone są wszystkie klasy a po zakończeniu obsługi usuwane &#8211; nie tak sobie wyobrażałem mój system rozproszony, zamiast w Pythonie mógłbym go napisać w PHP (sic!). Powrót do ZSI i eureka, ktoś bardziej doświadczony w tym języku dopisał kilka linii kodu do źródła i serwer stał się wielowątkowy! Połączenie idealne, wielowątkowość obsługi żądań, nie niszczenie wszystkiego po zakończeniu obsługi, możliwośc wypisywania komunikatów na ekran konsoli.<br />
Źródło rozwiązania: http://osdir.com/ml/python.pywebsvcs.general/2008-06/msg00019.html . Autor wykorzystał co prawda ZSI-2.1-a1, ale poprawka działa również na ostatniej stabilnej wersji ZSI-2.0</p>
<p>Na wszelki, skopiowany kod poprawki poniżej:</p>
<blockquote><p>&#8212; ZSI-2.1-a1/ZSI/ServiceContainer.py 2007-08-08 00:56:37.000000000 +0200<br />
+++ ServiceContainer.py 2008-06-19 13:50:11.000000000 +0200<br />
@@ -5,6 +5,7 @@</p>
<p>import urlparse, types, os, sys, cStringIO as StringIO, thread,re<br />
from BaseHTTPServer import BaseHTTPRequestHandler, HTTPServer<br />
+from SocketServer import ThreadingMixIn<br />
from ZSI import ParseException, FaultFromException,<br />
FaultFromZSIException, Fault<br />
from ZSI import _copyright, _seqtypes, _get_element_nsuri_name, resolvers<br />
from ZSI import _get_idstr<br />
@@ -30,6 +31,7 @@<br />
SimpleWSResource<br />
SOAPRequestHandler<br />
ServiceContainer<br />
+ ThreadedServiceContainer<br />
&#8222;&#8221;"<br />
class NoSuchService(Exception): pass<br />
class UnknownRequestException(Exception): pass<br />
@@ -141,12 +143,16 @@<br />
return SendFault(FaultFromException(e, 0, sys.exc_info()[2]), **kw)</p>
<p>-def AsServer(port=80, services=()):<br />
+def AsServer(port=80, services=(), threaded=False):<br />
&#8221;&#8217;port &#8211;<br />
services &#8212; list of service instances<br />
+ threaded &#8212; in modo multithread ?<br />
&#8221;&#8217;<br />
address = (&#8221;, port)<br />
- sc = ServiceContainer(address, services)<br />
+ if threaded:<br />
+ sc = ThreadedServiceContainer(address, services)<br />
+ else:<br />
+ sc = ServiceContainer(address, services)<br />
sc.serve_forever()</p>
<p>@@ -467,6 +473,11 @@<br />
def removeNode(self, url):<br />
self._nodes.removeNode(url)</p>
<p>+class ThreadedServiceContainer(ThreadingMixIn, ServiceContainer):<br />
+ &#8221;&#8217;Multithreaded version of ServiceContainer.<br />
+ &#8221;&#8217;<br />
+ pass<br />
+</p>
<p>class SimpleWSResource(ServiceSOAPBinding):</p></blockquote>
]]></content:encoded>
			<wfw:commentRss>http://piotr.doniec.eu/devlog/2010/01/soap-w-pythonie/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>HSSPOJ &#8211; zadanie które nie dawało mi spokoju</title>
		<link>http://piotr.doniec.eu/devlog/2010/01/hsspoj-zadanie-ktore-nie-dawalo-mi-spokoju/</link>
		<comments>http://piotr.doniec.eu/devlog/2010/01/hsspoj-zadanie-ktore-nie-dawalo-mi-spokoju/#comments</comments>
		<pubDate>Fri, 01 Jan 2010 19:37:11 +0000</pubDate>
		<dc:creator>pejotr</dc:creator>
				<category><![CDATA[Algorytmika]]></category>
		<category><![CDATA[Programowanie]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[spoj]]></category>
		<category><![CDATA[teoria gier]]></category>
		<category><![CDATA[tricky]]></category>
		<category><![CDATA[twierdzenie Sprague-Grundy'ego]]></category>

		<guid isPermaLink="false">http://piotr.doniec.eu/devlog/?p=381</guid>
		<description><![CDATA[Zadanie z konkursu algorytmicznego dla uczniów szkół średnich. Zwróciłem na nie uwagę, gdyż współczynnik poprawnych rozwiązań wynosił lekko ponad 30%, a skoro to konkurs dla licealistów to powinienem sobie dać radę. I tu pierwszy szok, nic z tego&#8230; Wiedza jaką dysponowałem okazała się daleko nie wystarczająca, a próby znalezienia rozwiązania podanego na tacy spełzły na [...]]]></description>
			<content:encoded><![CDATA[<p>Zadanie z konkursu algorytmicznego dla uczniów szkół średnich. Zwróciłem na nie uwagę, gdyż współczynnik poprawnych rozwiązań wynosił lekko ponad 30%, a skoro to konkurs dla licealistów to powinienem sobie dać radę. I tu pierwszy szok, nic z tego&#8230; Wiedza jaką dysponowałem okazała się daleko nie wystarczająca, a próby znalezienia rozwiązania podanego na tacy spełzły na niczym. Co dodatkowo rozbudziło moją ciekawość to fakt że na forach poświęconych programowaniu, nikt nie szuka pomocy.<br />
Zadanie finalnie okazało się rozbudowaną grą Nim, ale bez znajomości jednego twierdzenia teorii gier prawdopodobnie siedziałbym na tym jeszcze dłuuuugo&#8230;<br />
Treść zadania dostępna pod adresem <a href="http://www.spoj.pl/HSPLARCH/problems/HS09GAME/">http://hs.spoj.pl/problems/HS09GAME/</a><br />
<span id="more-381"></span><br />
Wspomniane twierdzenie to Twierdzenie Sprague-Grundy&#8217;ego. Gra przestawiona w zadaniu spełnia wszystkie założenia pozwalające na skorzystanie z twierdzenia. W połączeniu z dokładnie omówioną optymalną strategią, opisem pozycji wygrywających i przegrywających w grze Nim, pierwszą część zadania można rozwiązać w zaledwie 9 liniach</p>
<pre class="brush: python">
# gry - lista skladajaca sie z list reprezentujacych gre. Kazda reprezentacja
# gry to kolejna lista zaiwerajaca ilosc &#039;kijkow&#039; na kolejnych stosach
def graj(gry):
    sg = (0, 0, 1, 1, 2, 2, 3)
    for gra in gry:
        g = []
        reszty = []
        for stos in gra:
            reszta = int(stos)%7
            g.append(sg[reszta])
            reszty.append(reszta)
        wynik = reduce(lambda x,y: x^y, g)

        if wynik :
            print &quot;Julia wins.&quot;
        else :
            print &quot;Robert wins.\n&quot;
</pre>
<p>Lekki problem pojawia się przy ustalaniu ruchu wygrywającego. Nie wiem czy istnieje jakieś szybsze rozwiązanie niż takie trochę brute-force&#8217;owe która ja wykorzystałem. Polega ono na stwierdzeniu na jakiej pozycji ( wygrywającej czy przegrywającej ) znalazł by się gracz gdyby nie było jednego stosiku, a następnie obliczeniu czy da się odjąć taką liczbę patyczków żeby zostawić przeciwnika na pozycji przegrywającej.<br />
Dodatkowo oprócz wskazania ruchu wygrywającego należy wskazać ten podczas którego bierze się najwięcej patyczków ze stosu o najmniejszym numerze, co w lekki sposób komplikuje sprawę.:</p>
<pre class="brush: python">
        stos_wygrywajacy = 0;
        licznik = 0
        blokada_5 = False
        blokada_3 = False

        # odwrocenie list, sprawdzanie od konca
        gra_rev = gra[:]
        gra_rev.reverse()

        g_rev = g[:]
        g_rev.reverse()

        reszty.reverse()
        for reszta in reszty:
            # lista reszt bez kolejnych stosow
            tmpr = reszty[:]
            tmpr.pop(licznik)

            # xor wartosci f. Sprague-Grundy&#039;ego
            # bez kolejnych stosow
            tmpg = g_rev[:]
            tmpg.pop(licznik)
            tmpw = reduce(lambda x,y: x^y, tmpg ,0)

            if sg[reszta-5] == tmpw and int(gra_rev[licznik]) &gt;= 5:
                wygrywajacy = 5
                stos_wygrywajacy = len(reszty) - licznik
                blokada_5 = True
            elif sg[reszta-3] == tmpw and int(gra_rev[licznik]) &gt;= 3 and blokada_5 == False:
                wygrywajacy = 3
                stos_wygrywajacy = len(reszty) - licznik
                blokada_3 = True
            elif sg[reszta-2] == tmpw and int(gra_rev[licznik]) &gt;= 2 and blokada_5 == False and blokada_3 == False:
                wygrywajacy = 2
                stos_wygrywajacy = len(reszty) - licznik

            licznik += 1
</pre>
<p>Jeśli ktoś zna szybsze rozwiązanie chętnie je przeanalizuję <img src='http://piotr.doniec.eu/devlog/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /><br />
Zaznaczam, że nie dam sobie głowy uciąć że algorytm jest poprawny, bo nie ma już możliwości zgłoszenia rozwiązania &#8211; upłynęły terminy.</p>
<p><strong><em>EDIT</em></strong>:<br />
Lekko poprawiona wersja, działa trochę szybciej, natomiast i tak nie umożliwia zdobycia maximum punktów. Jesli nie ma jakiejś sztuczki na ruch wygrywający, a podejrzewam że coś jest, to lepiej zakodzić to w C&#8230;</p>
<pre class="brush: python">
        stos_wygrywajacy = 0
        blokada_3 = False
        blokada_2 = False
        licznik = 0
        for reszta in reszty :
            tmpg = g[:]
            tmpg.pop(licznik)
            tmpw = reduce(lambda x,y: x^y, tmpg, 0)

            if sg[reszta-5] == tmpw and int(gra[licznik]) &gt;= 5:
                wygrywajacy = 5
                stos_wygrywajacy = licznik + 1
                break
            elif sg[reszta-3] == tmpw and int(gra[licznik]) &gt;= 3 and blokada_3 == False:
                wygrywajacy = 3
                stos_wygrywajacy = licznik + 1
                blokada_3 = True
            elif sg[reszta-2] == tmpw and int(gra[licznik]) &gt;= 2 and blokada_3 == False and blokada_2 == False:
                wygrywajacy = 2
                stos_wygrywajacy = licznik + 1
                blokada_2 = True
            licznik += 1
</pre>
]]></content:encoded>
			<wfw:commentRss>http://piotr.doniec.eu/devlog/2010/01/hsspoj-zadanie-ktore-nie-dawalo-mi-spokoju/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>A może jednak Python?</title>
		<link>http://piotr.doniec.eu/devlog/2009/03/a-moze-jednak-python/</link>
		<comments>http://piotr.doniec.eu/devlog/2009/03/a-moze-jednak-python/#comments</comments>
		<pubDate>Wed, 18 Mar 2009 19:14:53 +0000</pubDate>
		<dc:creator>pejotr</dc:creator>
				<category><![CDATA[Odkurzone]]></category>
		<category><![CDATA[Programowanie]]></category>
		<category><![CDATA[Python]]></category>

		<guid isPermaLink="false">http://piotr.doniec.eu/devlog/?p=125</guid>
		<description><![CDATA[Do odkurzenia tego artykułu skusił mnie link przekazany przez kolegę: http://www.artima.com/weblogs/viewpost.jsp?thread=252441 . Związek jest dość luźny, pod linkiem jest raczej rozważanie na temat przyszłości języków programowania ich mutacji i wspomniane co nieco o Jython&#8217;ie. Poniższy wpis jest odkurzony i lekko przeredagowny. Python to język bardzo wysokiego poziomu w związku z tym tworzenie aplikacji w nim [...]]]></description>
			<content:encoded><![CDATA[<p>Do odkurzenia tego artykułu skusił mnie link przekazany przez kolegę: http://www.artima.com/weblogs/viewpost.jsp?thread=252441 . Związek jest dość luźny, pod linkiem jest raczej rozważanie na temat przyszłości języków programowania ich mutacji i wspomniane co nieco o Jython&#8217;ie. Poniższy wpis jest odkurzony i lekko przeredagowny.</p>
<p>Python to język bardzo wysokiego poziomu w związku z tym tworzenie aplikacji w nim powinno być szybkie. I może samo tworzenie jest, ale jak już się Pythona dobrze zna. Dostarczona dokumentacja jest średnio czytelna i korzystanie z niej nie było zbyt wygodne. Żeby korzystać z docs&#8217;ów Pythona trzeba mieć chyba jakiś dar.<br />
<span id="more-125"></span></p>
<h2><a id="core-documentation" name="core-documentation"></a></h2>
<blockquote><p>&#8222;Although both PHP and Python have excellent core documentation, Python&#8217;s is more extensive and generally higher quality.&#8221;</p></blockquote>
<p>No niestety nie moge się z tym zgodzić&#8230;<br />
Nie wiem jakie są powody że ludzie tak się zachwycają owym Pythonem. Ja bardzo się zniechęciłem gdy zobaczyłem że nie ma ani kwantyfikatowór dostępu, ani definicji pól klasy. Pola można sobie dodawać dowolnie w tracie działania, żadne deklaracje nie są wymagane. To takie wbudowane <em>__set</em> i <em>_call</em> z php.<br />
Napisanie programiku do logowania się do &#8222;wioski&#8221; w grze plemiona zajęło mi koło 2,5h.<br />
Linii mamy 32, co daje jakie 4,5 minuty na napisanie linii, a wiadomo że nie wszystkie linie są sobie równe.</p>
<pre class="brush: python">
import urllib, urllib2, cookielib

class PlemionaTool :
  def connect(self, username, password, world) :
    try:
      cookies = cookielib.CookieJar()
      self._world = world
      self._connection_handler = urllib2.build_opener(urllib2.HTTPCookieProcessor(cookies))
      headers = {&quot;User-Agent&quot;: &quot;Mozilla/5.0 (X11; U; Linux i686) Gecko/20071127 Firefox/2.0.0.11&quot;}
      login_data = urllib.urlencode({&quot;user&quot;: username,
                                              &quot;clear&quot;: &quot;true&quot;,
                                              &quot;password&quot;: password,
                                              &quot;server&quot;: world,
                                              &quot;login-btn-input&quot;: &quot;&quot;,
                                              &quot;cookie&quot; : &quot;false&quot;})
      request_http = &quot;http://www.plemiona.pl/index.php?action=login&quot;
      req = urllib2.Request(request_http, login_data, headers)
      self._connection_handler.open(req)
    except urllib2.HTTPError:
        print &quot;Jakis zonk&quot;

  def headquater(self) :
    response = self._connection_handler.open(&quot;http://&quot; + self._world +     &quot;.plemiona.pl/game.php?village=NUMER_WIOSKI&amp;amp;amp;amp;amp;amp;screen=main&quot;)
    page = response.read()
    return page

def main():
  pt = PlemionaTool()
  pt.connect(&quot;LOGIN&quot;, &quot;HASLO&quot;, &quot;SWIAT&quot;)
  print pt.headquater()

if __name__ == &#039;__main__&#039;:
  main()
</pre>
<p>Z zalet można wymienić wysokopoziomowość. Nie trzeba się męczyć z odbiorem, obróbką i wysyłaniem cookies, nie trzeba się też bawić z przechwytywć żadnego wyjątku  jak np. HTTPRedirect z Delphi.</p>
]]></content:encoded>
			<wfw:commentRss>http://piotr.doniec.eu/devlog/2009/03/a-moze-jednak-python/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

