Pierwsza infekcja

W środowisku piwowarów amatorów powiada się, że piwowarzy dzielą się na tych co już zaliczyli infekcję piwa i na tych, którzy zaliczą infekcję piwa. Prędzej czy później każdego to spotka, ponieważ produkujemy piwo w warunkach dalekich od sterylności — w kuchniach, piwnicach, a niektórzy wręcz na wolnym powietrzu. I pomimo dokładania wszelkich starań by możliwość zakażenia ograniczyć, nigdy nie usuniemy jej całkowicie.

No i właśnie moja warka #5 Petszopian Ogrodowy złapała infekcję. Podczas rozlewania do butelek zauważyłem kilka chmurek pływających w piwie, ale były malutkie, więc zabutelkowałem całą warkę, prawie 21 litrów. Następnego dnia gdy zamierzałem okleić butelki etykietami zauważyłem, że w każdej utworzył się cienki kożuch pleśni — najwyraźniej brak tlenu w fermentorze powstrzymywał rozwój infekcji, a gdy tylko otworzyłem pokrywę i powietrze dostało się do środka, zakażenie ruszyło z kopyta. Nie było sensu liczyć na cud, wylałem wszystko do ubikacji. Żal był przytłaczający.

Jak przy każdym niepowodzeniu, należy teraz usiąść spokojnie i przeanalizować okoliczności, żeby nie popełniać błędów w przyszłości. Co więc poszło nie tak?

  • Piwo bardzo długo stało na fermentacji burzliwej, bo aż 19 dni. Jak na temperatury w jakich przyszło mu fermentować to bardzo długo, bo rzeczywisty proces fermentacji prawdopodobnie zakończył się po 4-5 dniach.
  • Przyznaję się bez bicia, przelewanie na cichą było zrobione bez przykładania się do dezynfekcji. Spieszyło mi się bardzo.
  • Temperatura cichej fermentacji wahała się w okolicach 26-27ºC, bo nie chciało mi się wynosić fermentora do chłodniejszej piwnicy (niestety, niewiele chłodniejszej).

A jakie z tego płyną wnioski?

  • Nie warz piwa jeżeli nie będziesz w stanie zapewnić mu dobrych warunków przez cały czas jego powstawania.
  • Nie warz piwa jeżeli temperatury przekroczą zakres pracy drożdży.
  • Nie warz piwa w pośpiechu.

I teraz pozostaje mi mieć nadzieję, że zakażenie nastąpiło podczas przelewania na cichą lub w trakcie cichej fermentacji, bo gęstwą zebraną z tego piwa zaszczepiłem następną warkę...

Piwowarstwo domowe - ale po co to wszystko?

Nie można to już iść do sklepu i kupić sobie piwa jak normalny człowiek? W sklepowej lodówce stoi Tyskie, Lech, Żywiec, jak kto indywidualista to jest Łomża, Perła czy nawet Okocim (także Pszeniczne), po co się babrać z zacieraniem, gotowaniem, robieniem starterów i dezynfekowaniem w kółko tych samych kurków, wężyków, rurek i pojemników? I co gorsza nie jest to wcale tańsze niż piwo ze sklepu?

Pewnie że można. Pracuję w okolicy supermarketu Alma, gdzie wybór piwa jest naprawdę spory — jak kto chce, to kupi nawet Kölscha (11zł za 0.5l, w dodatku przeterminowany o jakieś pół roku), Witbiera (6zł za 0.33l) czy inne wynalazki. Piw polskich jest mało, ale czasem coś się da wybrać na wieczór przy kufelku.

No to o co chodzi? Kto się lubi pocić przez 6 godzin przy gorącym 30-litrowym garze, lepić się od słodkiej brzeczki i potem trząść się jak kura nad jajkiem, czy na pewno wszystko było zdezynfekowane i nie wdała się jakaś infekcja?

Warzenie własnego piwa w domu daje ogromną satysfakcję, że robi się coś, co jest niezwykłe. Dziś w Polsce mało kto próbuje samemu zrobić własne piwo. Satysfakcję tę pogłębia fakt, że piwo z domowego browaru smakuje zupełnie inaczej, niż to kupione w sklepie, obojętne czy jest to piwo na Ż czy na Ło. Piwo po prostu smakuje i pachnie piwem — czuć w nim słód i chmiel dokładnie tak, jak piwowar chciał (albo wyszło mu niechcący). Jeżeli ktoś lubi piwa bardziej goryczkowe, to daje więcej chmielu goryczkowego na początku gotowania, jeśli bardziej aromatyczne, to więcej chmielu aromatycznego pod koniec gotowania. Ze słodem można zrobić to samo, odpowiednio zacierając można uzyskać piwo bardziej lub mniej treściwe, z większą lub mniejszą zawartością alkoholu. A oprócz tego są jeszcze dodatki, którymi można sobie zmienić smak, zapach i kolor piwa, a wszystko zależy od inwencji i sprawności piwowara — nawet to, czy piwo będzie mocno nagazowane czy słabo i jaka będzie na nim piana. Piwo jest produktem tak złożonym, że nawet przygotowując dwa razy piwo według tej samej receptury, prawdopodobnie nie uzyska się takiego samego efektu.

I mnie to porusza. I dlatego chcę to robić.

Chcę warzyć wspaniałe piwa, które dają ludziom przyjemność.

Piwne peregrynacje

Moja wiejska posiadłość na okres letni miała stać się ośrodkiem browarniczym pełną gębą, ale coś mi się zdaje, że nic z tego nie będzie i cały szpej grzecznie wróci do domu. Niestety, jak się okazuje, warzenie w warunkach zbliżonych do naturalnych jest mocno kłopotliwe, jeżeli chce się to robić porządnie.

Przede wszystkim, warzenie piwa (obojętne z zacieraniem czy z ekstraktów) wymaga dużej ilości wody, zarówno spożywczej jak i technicznej (do chłodzenia, mycia i płukania). Wydawało mi się, że z warką ok. 22l zmieszczę się w 30l wody spożywczej i 40l wody technicznej. Okazało się, że proces wymaga minimum 40l wody spożywczej i 80l wody technicznej — w skrajnym przypadku jest to 12 wiader wody, którą trzeba przytargać do browaru.

Dodatkowym problemem jest konieczność ciągłego gotowania i chłodzenia, co wymaga dostępności od ręki odpowiedniej ilości zimnej wody i lodu. Jest to na tyle męczące, że ciężko jest skupić się na przyjemności warzenia — przez cały czas trzeba myśleć i ściśle pilnować się rozkładu, żeby nagle nie okazało się, że przed chwilą pomyliłem garnki i teraz nie mam w czym zagotować wody do dezynfekcji fermentora...

A teraz czas na trochę optymizmu — przeniesienie ośrodka produkcyjnego bliżej domu oznacza dokładnie to, że będę mógł więcej uwarzyć. Plan na miesiące czerwiec - wrzesień obejmuje:

  • co najmniej 2 warki pszeniczniaka, jak najbardziej zgodne ze stylem Hefe Weißbier — tu nie ma co eksperymentować, a naród pragnie pszenicy;
  • co najmniej 2 warki Kölscha celem dopracowania, to jedno z moich ulubionych piw i chciałbym, żeby wychodziło mi koncertowo;
  • na spróbowanie Grodzisz i jak posmakuje, to jeszcze w podobnym typie Berliner Weiße o ile pogoda (upały!) będzie tego wymagała;
  • podobnie na spróbowanie jakieś piwo z innych zbóż, może 6 Zbóż albo Roggenbier, a może wcale nie — to taki bufor bezpieczeństwa;
  • i we wrześniu koniecznie Düsseldorf Alt na zakończenie sezonu górniaków.

Jak widać, będę miał pełne ręce roboty — a potem będzie co pić. W większości w niemieckim stylu, ale nie szkodzi, na belgijskie klimaty górnej fermentacji przyjdzie jeszcze czas. ;)

Kto mnie dziś próbował zabić

Dziś jeszcze nikt. Może dlatego, że ogólnie rano ruch na ulicach Warszawy był raczej nieporażąjący intensywnością — z Bródna do Promenady na Ostrobramską (przez Ząbki i Chełmżyńską) udało mi się przejechać w około pół godziny, to wynik lepszy od przeciętnego o jakieś 15 minut. Oczywiście, paru idiotów po drodze spotkałem, ale nie zagrozili bezpośrednio mojemu bezpieczeństwu. Niestety, zagrozili bezpieczeństwu innych.

Bazyliańska

Na ulicy Bazyliańskiej w kierunku skrzyżowania z Wysockiego ruch w każdą stronę odbywa się po jednym pasie, a przestrzeń między kierunkami ruchu jest w zależności od miejsca albo pasem do skrętu w lewo, albo pasem rozbiegowym po skręcie w lewo w Bazyliańską, albo obszarem wyłączonym z ruchu. Nie brakuje jednak wsioków (przede wszystkim repów w Focusach i Astrach, ale i różni cywilni nie są lepsi), którzy z tej części ulicy robią sobie "lewy pas". I jadą, nie zważając po kolei na:

  • nakaz skrętu z pasa w lewo
  • to, że pas jest pasem do ruchu w kierunku przeciwnym
  • to, że powierzchnia jest wyłączona z ruchu
  • to, że ponownie pas jest pasem do ruchu w kierunku przeciwnym
  • i ponownie nakaz skrętu z pasa w lewo

Cały ten koncert buractwa kończy się koniecznością objechania wysepki przejścia dla pieszych, oczywiście jadąc pod prąd pasem dla ruchu w kierunku skrzyżowania z Rembielińską. Potem wystarczy już tylko wjechać na pas przeznaczony do skrętu w lewo w Wysockiego i... skręcić z niego w prawo.

Chełmżyńska

Przejazd kolejowy na Chełmżyńskiej to według mnie jedno z bardziej niebezpiecznych miejsc tego rodzaju w Warszawie. I nie ma wielkiego znaczenia to, że jest to przejazd strzeżony, z pełnymi zaporami opuszczanymi przy dozorze człowieka w budce obok zapór. Ruch na szlaku kolejowym między Rembertowem a stacją Warszawa Wschodnia jest bardzo intensywny i zawsze tworzą sie tam wielkie zatory, które skutkują kilkunasto- lub nawet kilkudziesięciominutowymi przestojami. A teraz trochę opisu słowno-muzycznego tego chorego miejsca (patrząc od strony Kawęczyna):

  • tuż przed przejazdem (dosłownie 3-4 metry przed zaporami!) jest przelotowe skrzyżowanie z ulicą Strażacką, na którą jest kierowany tranzyt samochodów ciężarowych w kierunku Lublina, a ze Strażackiej wyjeżdżają śmieciarki ze spalarni oraz kurierzy kilku firm, które mieszczą się w okolicy
  • tuż za przejazdem (w podobnej odległości od zapór!) jest skrzyżowanie z ulicą Chłopickiego, którą prowadzi skrót do placu Szembeka
  • na Chełmżyńskiej w kierunku Kawęczyna jest zakaz skrętu w lewo w Strażacką (tuż za przejazdem), ale nie ma zakazu skrętu w lewo z Chełmżyńskiej w Strażacką w kierunku przeciwnym (Marsa)

A jak to wygląda na żywo?

  • w kierunku Marsa przed przejazdem ciężarówki albo blokują przejazd przez tory czekając na możliwość skrętu w lewo w Strażacką, albo wymuszają pierwszeństwo przejazdu, blokując na torach pojazdy jadące w kierunku Kawęczyna
  • w kierunku Marsa za przejazdem skręcający z Chłopickiego w lewo w Chełmżyńską wymuszają pierwszeństwo przejazdu, blokując na torach pojazdy jadące w kiedunku Marsa
  • w kierunku Kawęczyna za przejazdem zawsze znajdzie się jakaś ciota, która pomimo zakazu zapragnie skręcić w lewo w Strażacką, blokując na torach pojazdy jadące za nią

Gwoli przypomnienia, cały ten cyrk odbywa się na przejeździe kolejowym, na szlaku, na którym pociąg przejeżdża przeciętnie co 2-3 minuty. Dróżnik może opóźnić zamykanie zapór, żeby umożliwić zjechanie z przjazdu, ale to zjechanie musi być możliwe — czyli skrzyżowanie po drugiej stronie przejazdu nie może być zablokowane. Jak na moje oko to jest tu trochę za dużo wymagań do spełnienia jednocześnie, by można było mówić o bezpiecznym przejechaniu przez ten przejazd (i 2 skrzyżowania!).

Ogólnie najwięcej zamieszania w tym rejonie wprowadziło otwarcie przejazdu ulicą Strażacką w kierunku Targówka Przemysłowego, przedtem ruch na skrzyżowaniu Chełmżyńskiej i Strażackiej był mizerny i raczej dotyczył skręcania ze Strażackiej w Chełmżyńską. Teraz codziennie jest tam straszliwy sajgon, a sytuacja chyba ma szansę poprawić się dopiero wtedy, gdy dojdzie tam do jakiegoś tragicznego wypadku.

I co dalej? Gdzie jest Policja?

Takich miejsc w Warszawie (i w każdym innym mieście) na pewno jest o wiele, wiele więcej. Każde z nich jest potencjalnie niebezpieczne, ale nie tak niebezpieczne, jak to niebezpieczne są skrzyżowania, na których nalezy przecież zachować wzmożoną ostrożność. Te miejsca są śmiertelnie niebezpieczne i tym bardziej dziwi mnie nieobecność Policji w tych okolicach. W ten właśnie sposób Policja zamiast być elementem systemu poprawy bezpieczeństwa na drogach, staje się czynnikiem zwielokrotniającym niebezpieczeństwo.

Slow train to dawn

...

V40, dzień pierwszy

Dziś kupiłem Volvo V40 2.0T. Pojeździłem sobie nim trochę i mogę poporównywać do poprzednika, Forda Escorta Mk7 kombi 1.6. Nie ma co porównywać osiągów, bo to zupełnie różne klasy aut, ale są jednak rzeczy, które się da porównać w miarę sprawiedliwie.

Zawieszenie w Escorcie jest twardsze. Przez to na równej drodze jedzie się nim pewniej, ale bardziej czuć wyboje. Ten samochód prowadzi się jakby miał włączony ESP, pewnie i z doskonałym wyczuciem drogi oraz przyczepności. Volvo jest miększe, przez co wymaga większej uwagi podczas jazdy w trudnych warunkach (jak dzisiejszy śnieg).

Układ kierowniczy Escorta jest dopasowany do zawieszenia — wspomaganie jest słabsze i wymaga nieco większego wysiłku, ale daje doskonałe wyczucie tego, co dzieje się z przednimi kołami. W V40 wspomaganie jest mocniejsze, przez co czasami ma się wrażenie mieszania w wiadrze budyniu.

Komfortu jazdy, przyspieszenia i elastyczności nie ma co porównywać — między silnikami B4204T3 i ZETEC-E jest przepaść związana z pojemnością (2.0 vs. 1.6), techologią rozrządu (DOHC VVT vs. prosty DOHC 16v) i dodatkowym osprzętem (turbosprężarka vs. nic).

Ciekawe, czy V50 ma z Focusa także zawieszenie i układ kierowniczy? Jeżeli tak, to ma szansę zbliżyć się do doskonałości. ;)

Diesel czy benzyna?

No właśnie, co wybrać? Diesel czy benzyna? I jedno i drugie kusi, a zwycięzca, jak w każdej rywalizacji (tu: o względy nabywcy), może być tylko jeden. Ja z uporem i systematycznie wybieram benzynę, choć nie w każdym przypadku — o tym może w innej opowieści. Ale najpierw trochę rozważań dla wyjaśnienia ewentualnych wątpliwości.

ON jest tańszy, wygrywa diesel!

Olej napędowy w kraju nad Wisłą rzeczywiście jest tańszy, czasem nawet znacząco. Że nie wszędzie panuje taka reguła mogą się przekonać ci, którzy zwiedzają inne kraje Europy: w Grecji różnica w cenie 1 litra paliwa wynosi 3-5 centów (np. w 2009 roku na Kos: benzyna EuroSuper €1.08/l, ON €1.05/l), a w Szwajcarii ON jest wręcz droższy od benzyny. Dlaczego, czyżby wytwarzanie oleju napędowego w tych krajach było droższe niż w Polsce? Oczywiście że nie, zastosowanie tej samej technologii daje podobny stosunek kosztów niezależnie od tego, gdzie jest ona używana. W każdym europejskim kraju najważniejszym czynnikiem kształtującym cenę paliwa są podatki nakładane przez państwo — przede wszystkim akcyzowy, ale także drogowy, ekologiczny i jakie sobie tylko rząd jest w stanie wymyślić (a inwencja rządów w tej dziedzinie nie ma granic, chyba każdy przyzna mi tu rację). To, że w Polsce ON jest tańszy np. o 20% od benzyny jest wynikiem tylko i wyłącznie tego, jakimi podatkami rząd okłada poszczególne rodzaje paliw. Silne lobby (transportowe, rolnicze, przemysłowe, itd.) w naszym kraju wymogło obłożenie ON niższym podatkiem akcyzowym, niż benzyny. A skoro ta różnica wynika tylko z decyzji administracyjnych, to nie można zakładać, że będzie trwała wiecznie — rząd zabiera mniej użytkownikom pojazdów napędzanych olejem napędowym, ale w każdej chwili może zmienić zdanie i eldorado się skończy.

Pozostaje jeszcze kwestia sezonowych wahań cen ON, rzeczy praktycznie nieznanej w przypadku benzyny. Jesienią i zimą cena oleju rośnie, po czym wiosną ponownie nieco spada, a rośnie tym bardziej, im niższe panują temperatury. Wynika to z faktu, że olej opałowy tak naprawdę to olej napędowy obłożony inną stawką akcyzy i dla odróżnienia barwiony na inny kolor. Latem większy udział paliwa z produkcji rafinerii jest sprzedawane jako olej napędowy, a jesienią i zimą jako opałowy. Ta akurat różnica nie jest spowodowana ingerencją państwa, ale zwykłym prawem podaży i popytu — malejąca podaż powoduje wzrost cen. Że nie są to groszowe sprawy mogą świadczyć pojedyncze przypadki, kiedy cena litra ON dorównała lub przekroczyła cenę litra benzyny.

Auto z silnikiem diesla pali mniej, wygrywa diesel!

Oczywista racja, z powodu wyższej sprawności silnika z zapłonem samoczynnym jego zapotrzebowanie na paliwo rzeczywiście jest mniejsze. Na ile mniejsze? Producenci aut prześcigają się w deklaracjach, jak to mały apetyt mają ich auta, podając czasem zawrotne wartości 4-4.5 l/100km dla silników 1.6 z wtryskiem w technologii Common Rail. W porównaniu do średnich 6-6.5 l/100km dla odpowiadających im silników benzynowych 1.6 16v DOHC z systemami zmiennych faz rozrządu to rzeczywiście mniej. Pamiętać jednak trzeba, że testy nie są przeznaczone do informowania o rzeczywistym zużyciu paliwa, a ich zadaniem jest umożliwienie porównania. Mając to na uwadze nie można powiedzieć, że silnik benzynowy o mocy ok. 115PS i pojemności 1.6 zużywa 2 litry paliwa więcej na 100km niż silnik wysokoprężny z CR o pojemności 1.6 i mocy ok. 105PS, a jedynie że takie wyniki zostały osiągnięte w warunkach laboratoryjnych. Dla naszego szarego życia w szarej rzeczywistości wynika z tego jedynie, że silnik wysokoprężny będzie zużywał mniej paliwa — a pytanie "ile mniej?" nadal pozostaje bez odpowiedzi.

Czas sięgnąć po dane z obserwacji. Różne serwisy prowadzą "dzienniki kosztów", z których można coś wywnioskować. Wynika z nich, że w normalnych warunkach różnice są mniejsze, niż podają producenci, a w skrajnych przypadkach w ogóle znikają! Co to są za przypadki? Ano, przypadki ciekawe:

  • pojazdy użytkowane wyłącznie w mieście;
  • pojazdy użytkowane na krótkich trasach, na tyle krótkich, że silnik nie zdąża rozgrzać się do swojej optymalnej temperatury pracy;
  • pojazdy użytkowane mało (na potrzeby tego artykułu można przyjąć, że jest to poniżej 20km dziennie).

Komu więc nie będzie się opłacał diesel? Taksówkarzom, ludziom, którzy wykorzystują auto wyłącznie do dojeżdżania do pracy na dystansie 3-4km i ludziom, którzy częściej auto myją, niż nim jeżdżą. A komu będzie się opłacał? Przedstawicielom handlowym i policji autostradowej.

Zespół napędowy, proste vs. skomplikowane, wygrywa benzyna!

Wspominałem już o tym przy okazji mojego wydziwiania nad silnikiem VAG 1.2 TSI — zespół napędowy w autach z nowoczesnym dieslem jest niezwykle skomplikowany, a więc również kosztowny w przypadku awarii. Zarówno wtrysk Common Rail, jak i pompowtryskiwacze (Pumpe Düse) to arcydzieła inżynieryjne, tak skomplikowane rzeczy po prostu muszą dużo kosztować. To, że wymagają dodatkowo paliwa o ściśle określonych parametrach wydaje się oczywiste, ale dodatkowo oznacza też, że każde odstępstwo od tych parametrów może skończyć się poważną awarią tych skomplikowanych i czułych elementów. O tym, że niektórym producentom (właściwie to jednemu czy dwóm...) udało się skonstruować silniki, które mają większy margines dopuszczalnych wartości parametrów zwanych potocznie jakością paliwa świadczy tylko o tym, jak bardzo skomplikowane są urządzenia wtryskowe w silnikach diesla.

Silnik wysokoprężny niemal zawsze obecnie jest wyposażony w turbosprężarkę, dającą mu dodatkowo wysoką elastyczność w szerokim zakresie prędkości obrotowych. Turbosprężarka (zwana potocznie turbiną, choć turbina to tylko jedna z jej części) to urządzenie z powodzeniem stosowane od ponad pół wieku w różnych silnikach, więc i konstrukcję ma zwykle dopracowaną w najmniejszym szczególe. Co nie znaczy, że nie można jej zepsuć. Użytkownicy silników 1.9 dCi z Renaultów, Nissanów czy Volvo aż za dobrze wiedzą, że można — ale ich przypadek jest szczególny, więc nas nie interesuje. Każdą turbinę można zniszczyć w ten sam sposób, obojętne czy silnik ma wtrysk CR czy PD (czy wręcz jest zasilany pompą rotacyjną). Ba, tyczy się to również turbodoładowanych silników benzynowych! Turbina wymaga szczególnego obchodzenia się z nią, a wynika to ze szczególnych warunków jej pracy — z tego, że jest napędzana gorącymi gazami spalinowymi. Jest kolejnym elementem, który wymaga chłodzenia i trzeba pamiętać o tym, żeby to chłodzenie jej zapewnić. Czyli: nie piłować silnika zanim się nie rozgrzeje i nie wyłączać go natychmiast po ostrej jeździe (wyłączenie silnika wyłącza obieg cieczy w układzie chłodzenia...).

No i ostatni element tej układanki skomplikowanych elementów — dwumasowe koło zamachowe w układzie sprzęgła. W skrócie chodzi o to, żeby nie przenosić wielkich obciążeń bezpośrednio z wału napędowego do układu jezdnego — te wszystkie szarpnięcia zmianami momentu obrotowego jakoś muszą zostać zamortyzowane, żeby nie dotarły do osi napędowej. Tym, co odpowiada za tę amortyzację jest właśnie koło dwumasowe, potocznie zwane dwumasem. W porównaniu do zwykłego koła zamachowego jest dużo bardziej skomplikowane, ale także jest narażone na dużo większe obciążenia. I niestety, żadnemu z producentów nie udało się skonstruować takiego koła dwumasowego, które byłoby trwałe i tanie. Mało tego, żadnemu nie udało się skonstruować takiego, które byłoby trwałe lub tanie — wszystkie są nietrwałe i drogie. Koszt wymiany przekracza zawsze 2 tys. zł, może być jedynie dużo więcej niż 2000 lub niedużo więcej niż 2000... Pewnym rozwiązaniem może być montaż zestawu 4P firmy Valeo, który zastępuje koło dwumasowe (i przez to jest tańszy), jednak nie do każdego modelu jest on dostępny.

Żeby nie było, że coś przemilczam, w niektórych modelach aut z silnikiem benzynowym również są montowane dwumasy — np. w poliftowych Volvo S/V40 (wszystkie poza silnikiem 1.6). Jednakowoż przypadki jego uszkodzenia są sporadyczne, a jest to związane z dużo mniejszymi przeciążeniami na wale napędowym. Niestety, ich koszt, przynajmniej w przypadku S/V40, jest dużo wyższy, niż do diesli...

To co ja mam wybrać?!

Ja Ci tego nie powiem (zajrzyj np. do Tylika: tu, tu i tu)... Zastanów się, na ile niższy koszt paliwa będzie w stanie zrekompensować Ci wyższy koszt serwisowania auta. Wyliczenie takie będzie dość proste przy nowym samochodzie, a używane będzie wymagało dokładniejszego sprawdzenia, czy wspomniane wysokoczułe elementy są w pełni sprawne (a i tak nie będzie gwarancji, czy nie padną w miesiąc po zakupie). Moje zdanie jest takie: do miasta lub przy przebiegach rocznych mniejszych niż 40 tys. km - benzyna, jeżeli w dłuższe trasy i na duże przebiegi - benzyna z gazem lub diesel.

A teraz pozostaje już tylko dokonać wyboru modelu i przeprowadzić udaną transakcję kupna, ale to już w innej opowieści...

Do 40-tki zostało...

Mam nadzieję, że uda mi się przekonać moją małżonkę, żeby wypuściła mnie na te parę dni z domu...

To samo na większej mapie.

Dziura, która znajduje się między Zagrzebiem a Debreczynem oznacza jak będę miał humor, to jeszcze skoczę do Grecji. ;)

Chcieli dobrze, wyszło jak zwykle

Pozwolę sobie trochę ponarzekać. Nie będzie to takie narzekanie, jak mojego sąsiada, osiadłego w Polsce Bułgara, chociaż temat ten sam — polskie drogi.

Przejechałem się dzisiaj w te i nazad do Warki. Droga do tej pięknej położonej malowniczo nad Pilicą miejscowości jest zasadniczo dobra: najpierw kawałek dwójką, potem siedemnastką, potem pięćdziesiątką i pod koniec kawałek jakąś drogą wojewódzką. Wiadomo, jak się jeździ — tak, żeby było szybko i bezpiecznie. Akurat tę trasę pokonuje się bardzo przyjemnie, ale tylko do momentu... skrzyżowania! Nie wiadomo jaka mądra głowa wpadła na pomysł, żeby np. skrzyżowanie dróg nr 17 i 50 zrobić w postaci ronda (i pozostałe z rozpędu też). Jak wiadomo, rondo służy poprawie bezpieczeństwa i płynności ruchu, ale nie wtedy, gdy na krzyżujących się drogach natężenie jest takie samo, a ruch odbywa się głównie na wprost. Wpływ na bezpieczeństwo jest taki, że objeżdżając wyspę trzeba odpowiednio zredukować prędkość, przez co ewentualne kolizje są mniej groźne w skutkach.

A jak to wygląda na tych kilku rondach na tej trasie? Dla ustalenia uwagi weźmiemy sobie wspomniane wcześniej rondo w miejscowości Kołbiel, na skrzyżowaniu dróg krajowych 17 i 50, ale pozostałe na tej trasie (czyli w sumie wszystkie skrzyżowania dróg krajowych i wojewódzkich!) prezentują się tak samo. Droga krajowa nr 17 to główna trasa z Warszawy na Ukrainę przez przejście w Hrebennem, a DK 50 to trochę dziwna droga łącząca m.in. wschodni odcinek DK 8/S8 (czyli szlaku na Litwę i Białoruś) z południową częścią DK 7/S7 (szlaku północ–południe). Ruch na tych obu trasach jest bardzo duży, a ciężarówki ciągną się tam długimi kolumnami. Przed tym rondem we wszystkich kierunkach korek zaczyna się 1.5-2km wcześniej. Tempo jest ślimacze, ponieważ ruszenie wielką, kilkudziesięciotonową ciężarówką wymaga nieco więcej czasu, niż ważącym niecałe 1.2t samochodem osobowym — zanim kierowca takiego wielkiego camiona wepchnie go na to rondo, mija ze 20 sekund (w tym czasie ze 2 samochody osobowe zdążyłyby wjechać i zjechać). I dlatego stoją wszyscy po równo. I nie ma litości dla tych, którzy tylko skręcają w prawo.

O ile ronda sprawdzają się doskonale na drogach o mniejszym natężeniu ruchu (jak np. doskonale wymyślone i zrobione rondo w Zielonce na skrzyżowaniu DW 637 i 634), to przy takim ruchu jak w Kołbieli są po prostu wąskimi gardłami. No, ale ronda są w modzie i przecież podnoszą bezpieczeństwo.

Wynoszę się z astera

Moi drodzy znajomi, zamieszanie, które wprowadził Aster ze swoim serwerem Jabbera skłoniło mnie do wyrejestrowania tam konta (rozleniwiłem się na starość). Kto chce nadal utrzymywać ze mną kontakt przez Jabbera, proszę używać mojego konta na gmailu — jarek kropka zgoda.

Rozterki wieku średniego

Wraz ze zbliżającą się 40-tką dojrzewam do kupienia sobie sportowego samochodu. Symptomatyczne dla wieku i przynależności do klasy średniej, jak sądzę. W związku z tym, że do 40-tych urodzin zostało jeszcze ponad półtora roku, na razie przechodzę etap wyboru obiektu. W sferze zainteresowania chwilowo są 3 modele dużych coupe robionych przez białych ludzi (bo niczego małego i robionego w Azji nie kupię) i jeden rezerwowy, gdyby kupienie żadnego z pozostałych nie wchodziło w grę:

Każdy z nich ma swoje plusy dodatnie i plusy ujemne, niestety. O co z Peugeotem chodzi, to wiadomo — jednorożec (więc ma największego plusa ze wszystkich konkurentów) ale bardzo trudno dostępny w stanie niezajeżdżonym i niebitym, a potem bynajmniej nie tani w utrzymaniu (szczególnie w wersji z silnikiem 3.0 V6 24v i to wcale nie z powodu apetytu na paliwo...). Mercedesów jest sporo i w pełnej gamie silników, ale w środku toto wygląda niestety jak taksówka i nie jestem pewien, czy jazda takim czymś sprawi mi przyjemność. Cougarów na rynku jest przeciętnie dużo, ale to nowy zawodnik w mojej stawce i muszę się do niego przekonać. Na plus przemawia to, że to znajomy Ford i jego cena, a na minus... pochodzenie od Mondeo Mk2. Przeciwko Volvo przemawia mała podaż i wysoka cena. Poza Mercedesem wszystkie te samochody mają entuzjastyczne oceny od swoich właścicieli i gdyby nie duża podaż CLK to nawet nie spojrzałbym w jego stronę. Ostatnia nadzieja w paru znajomych, którzy sprowadzają auta z Niemiec, może na tamtym rynku uda się coś ciekawego wyrwać.

Większość konkurentów (poza, oczywiście, Peugeotem) nie dostąpiła jeszcze zaszczytu przewiezienia mnie, więc najważniejsza próba dopiero przed nimi. Jeszcze trochę czasu na podjęcie decyzji mam, ale szykuje się ciekawy rok...

Kłamstwa statystyki

Auto-Świat zapłakał nad bezpieczeństwem na polskich drogach, ale łzy to były raczej krokodyle... Handlowcy postrachem dróg, tak się tytułuje ten artykuł. Wynika z niego przerażająca wizja zabójców w firmowych samochodach, którzy powodują niewspółmiernie dużo wypadków. Niewspółmiernie do swojej ilości — podobno kierowcy 8% pojazdów powodują 30% wypadków i oczywiście coś trzeba z tym zrobić.

Bzdura. Piramidalna.

Liczby wyglądają alarmująco, ale tylko do czasu, gdy porówna się ile te auta jeżdżą. Przeciętny kierowca takiej służbówki robi rocznie 40-60 tysięcy km (podobno 100 tysięcy też nie jest niczym niezwykłym). Dla porównania, przeciętny nalot prywatnego auta to 12-15 tysięcy km, a sporo ludzi jeździ swoimi samochodami po 5 tysięcy km rocznie, większość moich sąsiadów nie przejeżdża nawet 100 km tygodniowo żeby wyrobić te 5 tysięcy. Żeby taka statystyka miała w ogóle sens, należałoby liczyć nie sztuki, a przejechane kilometry — ilość spowodowanych wypadków na tysiąc czy 10 tysięcy przejechanych kilometrów. Wtedy można byłoby porównywać — zwłaszcza, że wypadki powodują ludzie, a nie pojazdy (no, może poza ewidentnymi przypadkami samopodpalających się Peugeotów...).

Tak że: spokojnie. To tylko statystyka + nieuprawnione wnioski.

Dla potomności

Jutro jadę do pracy samochodem. :D

Już mogę płacić haracze

Załatwiłem ostatnią sprawę, związaną z rejestrowaniem działalności gospodarczej. Po 27 dniach od złożenia wniosku o wpis do ewidencji mogę wreszcie w majestacie prawa płacić haracz okupantowi.

Drogi krzyżowej przedsiębiorcy ciąg dalszy

Dziś nie wytrzymałem i zadzwoniłem do Urzędu Statystycznego w Warszawie dowiedzieć się, co się dzieje z moim numerem REGON (dla ustalenia uwagi: wniosek o wpis złożyłem 1 kwietnia, wpis odebrałem 8 kwietnia). Jak się okazuje, mój numer wypłynął z US 15 kwietnia zwykłą pocztą i do 20 kwietnia nie był w stanie pokonać 25 kilometrów do Wołomina.

Ale przynajmniej wiem, że istnieje...

Bez dumy

Zainspirowany komentarzem tylika przemyślałem sobie jeszcze raz kwestię mojej odysei egzaminacyjnej. Tylik, ja naprawdę nie mam się czym chwalić.

Mam 38 lat, od około 20 jeżdżę różnymi pojazdami, małymi i dużymi, szybkimi i wolnymi, na gąsienicach i na kołach, takimi co pływają i takimi, co się ledwo toczą, od Fiata 126p do BRDM-2, od Ursusa C-330 do BWP-1 (zgadza się, dłużej jeżdżę, niż piszę programy!). Wydawało mi się, że z takim doświadczeniem zdanie egzaminu państwowego będzie niemal formalnością, jednak przykładnie odjeździłem wszystkie jazdy, na luzaku przyjechałem w grudniu na egzamin i... przeżyłem pierwszy szok, gdy oblałem egzamin na łuku. Dlaczego, przecież niewiele to się różni od wyjeżdżania na parkingu czy z garażu (w przypadku naszego garażu jest nawet mniej miejsca)? Zagadka. Potem zagadek było jeszcze więcej — na egzaminie robiłem rzeczy, o które sam bym się nie podejrzewał, że w ogóle potrafię. Dopiero za piątym razem pozbierałem się jakoś i wreszcie ten egzamin zdałem. Do nikogo nie mogę mieć pretensji poza sobą.

Wszystko to może świadczyć o tym, że moje zdanie o sobie samym jest całkowicie błędne — psychicznie daleko mi do zimnego twardziela, który każdy stres bierze na miękko, robi co ma zrobić i idzie na wódkę po skończonej robocie. Dlatego właśnie czuję się psychicznie złomotany, pomimo tego, że oczywiście cieszę się ze zdanego egzaminu i zakończenia okresu przejściowego. Jednym zdaniem: powód do radości tak, ale do dumy to już nie — jest się z czego cieszyć, ale nie ma czym chwalić.

Co oczywiście nie psuje mi nastroju na tyle, żebym siedział w kącie i pochlipywał pod nosem — trzeba się zająć nową sytuacją na poważnie. Tylik ma swojego jednorożca, mam i ja ;). Celuję trochę niżej: Peugeot 406 Coupe 3.0 V6, ale przez to mam nadzieję ustrzelić sztukę nieco mniejszym wysiłkiem (głownie finansowym). Pewnie jeszcze trochę o tych polowaniach na mojego jednorożca tu się pojawi, a z obecnego stanu rynku (okazy można znaleźć np. na allegro) wnioskuję, że parę sztuk zląduje też na bezwypadkowe.net.

Podsumowanie

jarek:~$ ipython

In [1]: import datetime

In [2]: d0 = datetime.date(2008, 9, 13)

In [3]: d1 = datetime.date(2009, 4, 14)

In [4]: d1 - d0
Out[4]: datetime.timedelta(213)

In [5]: 1500 + 25 + 5 * 115 + 500 + 300 + 200 + 250 + 200 + 150
Out[5]: 3700

In [6]:

213 dni, 3700 złotych, 6x potworny stres — tyle naprawdę kosztowało mnie prawo jazdy. 9000 wydane na Escorta przy tym to pryszcz. Można sobie zadawać pytanie, czy to musiało tyle kosztować i pewnie nie musiało (gdybym np. od razu wykupił kurs rozszerzony z 40 godzinami jazdy zaoszczędziłbym 200 złotych), ale zysk na pieniądzach tak naprawdę miałby znaczenie drugorzędne, najbardziej dla mnie liczyłby się czas i przeżyty stres.

Najważniejsze, że mam to już za sobą.

Setuptools to szajs

Wiele było już głosów, że setuptools jest pełne błędów i nie powinno być używane. W mojej praktyce na te błędy nie trafiałem, więc poprzestawałem na niechęci, a drobne wpadki powodowały jedynie wzrost przychylności wobec antagonistów setuptools. Tym razem w ciągu ostatnich dni zostałem doświadczony dwukrotnie przez poważne niedoróbki w setuptools, w tym jedna ma znaczenie krytyczne (nie instaluje się część zawartości pakietu):

Setuptools musi odejść!

"Jedno okienko"? Oczywiście, że jedno!

Od wczoraj obowiązuje ustawa, która miała przedsiębiorcom rozpoczynającym działalność ułatwić życie — wszystkie sprawy związane z rozpoczęciem działalności gospodarczej miały być załatwione podczas jednej wizyty w magistracie, przy jednym okienku właśnie. Wczoraj odwiedziłem mój Urząd Miasta, ale pani w tym jednym okienku poprosiła, żebym przyszedł następnego dnia, jeżeli mi się nie spieszy z rozpoczynaniem działalności (albo spieszy mi się dokądś), bo ona nie do końca wie, jak to wszystko pozałatwiać, pomimo tego, że była na jakimś szkoleniu i nawet jej instrukcję dali. Pobiedziłem się wczoraj wieczorem nad formularzem EDG-1 i przyszedłem dzisiaj rano...

Okienko faktycznie jest jedno. To znaczy — są dwa, ale tylko jedno czynne. Kolejka może nie była szczególnie długa, ale posuwała się potwornie wolno, bo pani przyjmująca druki przy każdej sprawie musiała dzwonić w przynajmniej jedno miejsce, żeby zasięgnąć dodatkowych informacji (do Urzędu Skarbowego albo do ZUS). A czasem musiała dzwonić w oba... Średni czas załatwienia jednego interesanta: około 60 minut. Po około 2 godzinach przyszedł czas na mnie. Na szczęście dobrze odrobiłem pracę domową wczoraj i mój wniosek nie wymagał żadnych korekt, więc załatwiłem sprawę w pół godziny i z jednym telefonem do przyjaciela (w Urzędzie Skarbowym).

A teraz zauważone idiotyzmy:

  • wraz z wnioskiem można podać numer konta bankowego dla firmy, ale żeby założyć konto na firmę, to trzeba mieć wpis do ewidencji i REGON: +1 okienko;
  • we wniosku można podać dane firmy rozliczającej księgowość, ale umowę podpisuje się dopiero po uzyskaniu wpisu do ewidencji i REGON: +1 okienko;
  • we wniosku nie można podać sposobu rozliczania VAT: +1 okienko;
  • wraz ze składaniem wniosku nie można zgłosić płatnika składek i ubezpieczonego do ZUS: +1 okienko.

I jeden, jedyny plus, jaki w tym wszystkim jest: działalność można rozpocząć w dniu składania wniosku o wpis do ewidencji. Dobre i tyle, chociaż wciąż nie można podpisać żadnej umowy (bo przecież nie ma się wpisu do ewidencji ani REGON).

Wszystko to wygląda na krok w dobrą stronę, ale raczej głupio zrobiony.

Oko na RSS

Nie nie chodzi o żadne feedy, tylko o tzw. resident set aplikacji w Django. Obserwuję tę wartość od dłuższego czasu dla tej małej aplikacyjki i z pewnym niepokojem obserwuję jak rośnie, od ~15MB pod koniec 2007 roku przez ~17MB w okolicach wydania 1.0 do ~19MB z wersją 1.1-beta1 (przy wręcz zmniejszającym się feature secie aplikacji). A mój niepokój bierze się z mojej zadziwiająco dobrej pamięci, jak na mój podeszły wiek.

Kiedyś, w zamierzchłych czasach (okolice Slackware 9.0, czyli początek 2003 roku), była sobie fajna, mała przeglądarka WWW, która nazywała się Phoenix. Wyrosła z potrzeby istnienia po prostu przeglądarki i w swoich bebechach była Mozillą (tak się kiedyś nazywała przeglądarka wyrosła z Netscape Communicatora) bez wszystkiego tego, co nie służyło przeglądaniu stron WWW. Była szybka, miała małe wymagania i wszyscy ją pokochali od razu. Pokochali ją tak bardzo, że Mozilla Foundation postanowiła skupić na niej swoje wysiłki developerskie. W szybkim tempie (od wersji 0.4 Oceano z listopada 2002 do wersji 0.8 Royal Oak z lutego 2004) program zbliżył się apetytem na zasoby do swojego rodzica i przestał być postrzegany jako lekki i szybki. Po 7 latach istnienia Mozilla Firefox wciąż bohatersko zwalcza bloat, który był głównym powodem jego wypączkowania z projektu Mozilla Suite.

Na ile ostatnie develpmenta w Django przypominają to, co stało się z Phoeniksem? Na tyle, że nagle wszyscy pokochali Django i zaczęło ono obrastać w rzeczy, które już nie mieszczą się w legendarnych 80% (i django.contrib.gis to naprawdę mały pikuś w tym zestawie). Wygląda na to, że zadowalanie coraz większej rzeszy użytkowników daje w wyniku coraz większe zapotrzebowanie na zasoby...

Rekapitulując, ja też uważam, że martwię się na zapas. Sytuacja sama w sobie nie wygląda jeszcze na niepokojącą, niepokojący jedynie może być ten trend. Czy doprowadzi do tego, że Django przejdzie na ciemną stronę mocy, to się dopiero okaże.

Koniec Last.fm?

Last.fm zapowiedziało wprowadzenie opłat za streaming audio we wszystkich krajach poza Niemcami, Wielką Brytanią i USA. Podobny ruch Pandory (a następnie zamknięcie jej dla użytkowników spoza USA) doprowadził do niemal całkowitego jej zniknięcia ze sceny.

Jak każdy odmawiam płacenia za coś, co do tej pory było free. Trudno, najwyżej nie będę słuchał ich radia — ściągnę sobie co trzeba skąd się da...

Żarte aplikacje na AppEngine

Aplikacja, która jest moją piaskownicą na Google AppEngine z upływem czasu rozrosła się trochę (procesory kontekstu, middleware, takie tam...) i okazało się, że każdy request w przeglądarce logów świeci na żółto, to znaczy że według Google jego obsługa zjadła nadmierną ilość zasobów i powinien zostać w jakiś sposób zoptymalizowany. No i faktycznie, powinien — obsługa każdego z żądań do aplikacji zjadała ~1200 ms CPU (łącznie kod + storage). Coś było ewidentnie nie halo, więc musiałem podjąć pewne kroki zaradcze:

  1. użycie googlowego cache gdzie się tylko da (porzucając tradycyjne pojęcie o tym, gdzie ma to sens);
  2. optymalizacja sposobu dostępu do danych w datastore (wybieranie encji używając klucza/kluczy, a nie budując Query);
  3. jak dla mnie najważniejsze: optymalizacja importów.

Zanim przejdę do omówienia poszczególnych optymalizacji... Warto było nad tym popracować, bo średni czas obsługi żądania spadł do ~120 ms CPU (z grubsza: 10x wzrost wydajności). Pomimo tego, co ja uznałem za najważniejsze, to nie optymalizacja importów dała największy zysk, a zmniejszenie ilości odczytów z datastore (dzięki użyciu memcache i wybierania danych przy użyciu kluczy). Co uważam za dobre w tym wszystkim to to, że AppEngine wymusza przemyślane zaplanowanie aplikacji i optymalizację każdego aspektu działania kodu (i to od samego początku). To nie jest zabawka dla niecierpliwych chłopców-pehapowców. ;)

Memcache gdzie się da

Memcache API było jedną z pierwszych rzeczy, jakie Google dodało do AppEngine po jego uruchomieniu w kwietniu 2008 roku. Jego użycie w aplikacji jest nie tyle optymalizacją, co po prostu koniecznością (szczególnie w świetle zapowiedzianego na koniec maja 2009 obniżenia limitów). O ile w zwykłych aplikacjach w cache umieszcza się rzeczy, które są albo kosztowne do wyliczenia, albo niemal statyczne, o tyle na AppEngine buforować trzeba niemal wszystko, bo pomimo twierdzeń googlarzy, że odczyty z datastore są tanie, to ta taniość jest względna (chyba względem kosztu zapisów) — a koszt obsługi żądania jest liczony jako suma kosztu wykonania kodu jako całości, wraz z kosztem pobrania danych (w limitach te wartości są liczone oddzielnie).

Na co zwrócić uwagę na początku? Na drobne rzeczy: profil użytkownika, listy ostatnio dodanych/popularnych obiektów, to, co pojawia się w kontekście w wyniku działania procesorów lub jest dodawane do obiektu request przez middleware. Po tych rzeczach można zająć się resztą, czyli każdą instancją modelu (i każdą wyliczoną wartością), która pojawia się w aplikacji. Czasem trzeba będzie podjąć decyzję, czy warto aktualizować pokazywane dane w czasie rzeczywistym, czy może da się przełknąć mały poślizg rzędu 15 minut... Bo obiekty wyjęte z cache nie zawsze zachowują się tak, jak byśmy tego oczekiwali (przynajmniej na razie).

Dostęp do danych

Tym, co bywa najtrudniejsze do przełknięcia przy robieniu aplikacji na AppEngine jest zupełnie inny model storage — nierelacyjny, bez złączeń i nastawiony na zupełnie inne użycie, niż bazy danych ogólnego stosowania, jak MySQL czy PostgreSQL (nie ujmując nic relacyjnym bazom danych). Oczywiście, można udawać, że się tego nie zauważa i próbować symulować relacyjność, ale efektem tego będzie obniżona wydajność. Z tego co zauważyłem w różnych artykułach i podpowiedziach tu i ówdzie, najważniejsze podpowiedzi można streścić w kilku punktach:

  • storage świetnie sprawdza się jako wielka tablica asocjacyjna, dostęp do danych przy użyciu kluczy jest najbardziej wydajny;
  • klucze są jedynymi unikalnymi atrybutami obiektów, można to wykorzystać do kilku celów;
  • przechowywanie listy kluczy (np. w atrybucie typu db.ListProperty) jest równie wygodne jak złączenie wiele-do-wiele, a w większości wypadków wygodniejsze;
  • atrybuty indeksowane (db.StringProperty) są bardziej kosztowne w aktualizacji niż nieindeksowane (db.TextProperty), warto wziąć to pod uwagę przy projektowaniu modelu.

Uwaga na importy

Czym się różni kod uruchamiany na AppEngine od kodu uruchamianego w zwykłym środowisku Pythona? Niczym, oprócz tego, że proces, który obsługuje żądanie żyje dokładnie tyle, ile trwa obsługa żądania. A to oznacza, że wszystkie moduły konieczne do wykonania kodu przy każdym żądaniu muszą zostać zaimportowane, co jest sporym obciążeniem. Aby trochę poprawić sytuację, AppEngine buforuje zaimportowane moduły przez jakiś czas (liczony raczej w sekundach niż w godzinach). Nie są buforowane moduły, które zostały zaimportowane przy użyciu funkcji __import__(), co oznacza tylko jedno: wszystkie wynalazki typu klass = import_string('mypackage.mymodule.MyClass') trzeba odłożyć na półkę. Nie zawsze da się tego całkiem uniknąć, ale w takich przypadkach trzeba przygotować swój kod na to, że może otrzymać obiekt wykonywalny lub ciąg znaków i zminimalizować ilość miejsc, gdzie wykonywany jest niebuforowany import.

Dużo tego, ale nikt nie mówił, że będzie lekko. :)

Koniec darmowych obiadków

Google zapowiedziało, że za trzy miesiące zmniejszy darmowe limity na AppEngine, a od 24 lutego można sobie zwiększyć limity, dopłacając (drobne bo drobne, ale zawsze) parę dolarków. Moje aplikacje są w takim stadium, że tak naprawdę mnie to nie będzie dotyczyło, ale zmniejszenie limitów przy jednoczesnym wprowadzeniu opłat jak dla mnie coś oznacza — Google przygotowuje się na przetrwanie kryzysu w IT ograniczając wydatki. Może to być także oznaką tego, że uznali AppEngine za produkt na tyle dojrzały, że można za niego brać pieniądze (choć według mnie jeszcze sporo do tego brakuje). Redukcja limitów jest spora, bo w przypadku ilości przesłanych danych to jest 90% (z 10GB do 1GB/24h), a w przypadku obciążenia CPU 86% (z 46 godzin do 6.5 godziny/24h). Na blog czy inny maleńki serwis to może i wystarczy, ale nie daj Boże żeby ktoś się tym poważnie zainteresował, bo limit się wyczerpie w pół godziny. Biorąc pod uwagę dodatkowo fakt, że Google nie powiadamia o zbliżającym się wyczerpaniu limitów (np. po przekroczeniu 80% któregokolwiek z nich), można się nagle obudzić z ręką w nocniku. Nie zmienia to oczywiście faktu, że tą platformą nadal warto się interesować i nawet w wersji płatnej wciąż jest ciekawą propozycją do budowania aplikacji, choć już nie tak atrakcyjną.

Tak czy inaczej, chwilowo nie zamierzam się tym przejmować, choć trudno przewidzieć, jak sytuacja będzie się przedstawiała za trzy miesiące. Na razie staram się robić moje aplikacje w ten sposób, żeby przeniesienie ich na normalny hosting nie wymagało przepisywania całości (co kosztuje więcej zachodu, niż mogłoby się wydawać, ale o tym innym razem).

Zrób swoje własne Django, odc. 2 - procesory kontekstu

Obiecałem, że będzie o procesorach kontekstu jak w Django (a może nawet trochę lepszych), więc proszę.

Procesory kontekstu

Procesor kontekstu wg. Django to kod wykonywalny, który przyjmując obiekt request zwraca słownik, który następnie jest dodawany do kontekstu przed renderowaniem szablonu. W ten sposób można zapewnić sobie dostępność pewnych danych w kontekście bez potrzeby pamiętania o tym, by te dane tam umieścić. W Django procesory kontekstu są wywoływane wtedy, gdy używa się klasy RequestContext. Pół biedy, gdy chodzi o mój kod — już ja o to zadbam, żeby tam był użyty RequestContext, ale problemem może być kod, którego autor o tym nie pomyślał.

Używając Jinja2 i Werkzeug nie możemy liczyć na tak silną integrację systemu szablonów z modelem żądania i odpowiedzi (założenia obydwu komponentów właśnie taką integrację wykluczają). Na szczęście zarówno Jinja2 jak i Werkzeug dostarczają nam wszystkiego czego potrzeba, żeby zaimplementować sobie taką funkcjonalność. Niestety, nie będzie tak prosto jak w przypadku middleware.

Werkzeug posiada coś, co jest nazywane local proxy — jest to wariant thread local storage, specjalnie przystosowany do potrzeb aplikacji webowych. Zazwyczaj umieszcza się w nim kod aplikacji WSGI (klasy lub funkcji), ale nie ma przeszkód, żeby umieścić tam cokolwiek innego, np. obiekt request:

def __call__(self, environ, start_response):
    local.application = self
    local.request = request = Request(environ)

Tak umieszczony obiekt request będzie następnie dostępny w dowolnej innej części aplikacji w trakcie jej czasu życia (czyli przetwarzania żądania i produkowania odpowiedzi). Teraz w okolicy mojego kodu renderującego szablon mogę zrobić taki myk:

def build_globals():
    jinja_globals = {}
    for item in getattr(settings, 'CONTEXT_PROCESSORS', []):
        try:
            processor = import_string(item)
            jinja_globals.update(processor(local.request))
        except (ImportError, AttributeError):
            pass
    return jinja_globals

jinja_env = Environment(loader=FileSystemLoader(settings.TEMPLATE_DIRS))
jinja_env.globals.update(build_globals())

Chodzi o to, że Jinja2 posiada tzw. globalne zasoby — można je zmodyfikować po utworzeniu środowiska a przed wyrenderowaniem pierwszego szablonu. Od teraz w każdym szablonie będzie dostępne to, co znajduje się w moim słowniku jinja_env.globals. A co się tam może znaleźć? Na przykład to:

def messages(request):
    messages = request.environ['beaker.session'].get('messages', [])
    request.environ['beaker.session']['messages'] = []
    request.environ['beaker.session'].save()
    return {
        'MESSAGES': messages,
    }

Czemu jest to lepsze rozwiązanie niż w Django? Ponieważ nie trzeba pamiętać o tym, żeby kontekst był obiektem klasy RequestContext. Dzięki buforowaniu środowiska przez Jinja2, narzut jest minimalny, a prostota rozwiązania kusząca. Czyżby więc było to rozwiązanie idealne? W moim przypadku nie. Trzeba bardzo uważać na to, by zaimportować ten kod w odpowiednim momencie (dla uproszczenia umieściłem go w przestrzeni globalnej). Ale działa i robi dokładnie to, co chciałem.

Ten kod nie powstałby, gdyby nie Ali Afshar (tak, ten od PIDA), który podał rozwiązanie tego problemu na StackOverflow.

Zrób swoje własne Django, odc. 1 - middleware

Żartuję, Django jest na tyle dobre, żeby nie musieć go robić samemu. Chodzi mi raczej o sytuację, kiedy chce się mieć tyle Django, ile trzeba i ani trochę więcej (na przykład dlatego, że z całego oryginalnego Django wykorzystuje się tylko parę komponentów, bo na więcej nie pozwala AppEngine). Z pomocą przychodzi Werkzeug, Beaker i Jinja2 i parę innych bibliotek. Oprócz oczywistego zysku, jakim jest odchudzenie narzędziówki o kilka cennych setek plików, można zyskać bezcenną wiedzę, jak działa Django (im więcej wiem, tym większym podziwem darzę core devs, bo Django okazuje się jeszcze lepsze, niż wygląda na pierwszy rzut oka).

W paru kolejnych odcinkach opiszę rzeczy, które uznawałem za bardzo użyteczne w Django i zaimplementowałem sobie jako uzupełnienie narzędziówki (inna rzecz, że niełatwo jest się wyrzec niektórych przyzwyczajeń).

Middleware

Nie chodzi mi o middleware w rozumieniu WSGI, lecz takie, jak w Django — metody zwykłych klas, które są wywoływane z ustalonymi argumentami w określonych momentach przetwarzania żądania i odpowiedzi. Niespodzianka, Werkzeug ma już coś takiego! Nazywa się to Processor i klasa, która znajduje się w module werkzeug.contrib.kickstart pokazuje, jak powinien wyglądać kompletny interfejs takiej klasy i sygnatury jej metod. Leniwi mogą sobie z tej klasy po prostu odziedziczyć...

Pozostaje jedna rzecz, czyli podłączenie tego cuda do naszej aplikacji WSGI. Poniżej fragment mojej metody __call__() z klasy reprezentującej aplikację WSGI. Podłączam w niej tylko jeden rodzaj middleware (są jeszcze 3 inne możliwe).

for item in getattr(settings, 'MIDDLEWARES', []):
    try:
        klass = import_string(item)
        middleware = klass()
        response = middleware.process_request(request)
    except (ImportError, AttributeError):
        pass
    if response is not None:
        break
if response is None:
    local.url_adapter = adapter = url_map.bind_to_environ(environ)
    try:
        endpoint, values = adapter.match()
        handler = import_string(endpoint)
        response = handler(request, **values)
    except HTTPException, e:
        response = e

Inny sposób na podłączenie do kodu aplikacji WSGI można znaleźć na wiki Werkzeug — jak zwykle pełna wolność wyboru metody (oczywiście, działa dobrze w każdym przypadku).

W następnym odcinku

A w następnym odcinku okaże się, jak zrobić procesory kontekstu (context processors) takie jak w Django, a nawet lepsze. Tym razem w użyciu będzie zarówno Werkzeug jak i Jinja.

Trzecie koty za płoty

Oblałem egzamin praktyczny na prawko po raz trzeci. Nie wiem jeszcze kiedy poprawka, bo dopiero we wtorek będę miał kwitek z doszkalania.

Tym razem już niewiele brakowało — już woziliśmy się na czas, bo program obowiązkowy miałem już zaliczony.

Nie ma epidemii grypy

W dodatku warszawskim do wczorajszego SuperExpresu pojawił się artykuł alarmujący, że w naszym wojewódzwtwie na grypę zachorowało już ponad 4000 osób i stawiający odważną tezę o szalejącej epidemii. W 2008 roku województwo mazowieckie miało ponad 5100000 mieszkańców (słownie: pięć milionów sto tysięcy), jeśli wierzyć Głównemu Urzędowi Statystycznemu. Co oznacza, że na grypę zapadło... 0.08% mieszkańców. Zaiste, epidemia...