Komputery, oprogramowanie, internet i okolice
Kategorie: Wszystkie | Aplikacje | Blog | Dev | Hacks | Linux | Subversion | Varia | gry | khoomei | książki | mjuzik
RSS

Dev

piątek, 29 kwietnia 2011

Cóż... Na starość człowiek geeczeje, a do głowy przychodzą różne głupie pomysły. I tak zamiast kończyć przygotowania do wydania nowej wersji Python Window Organizera w wolnej chwili postanowiłem pobawić się modelami jednej z moich ulubionych gier.

Quake MDL Loader

Stój bo strzelam!

Korzystając ze znakomitego opisu formatu plików MDL autorstwa Davida Henry'ego (warto też zerknąć do Unofficial Quake Specs) napisałem sobie prosty pythonowy programik wczytujący modele z Quake'a 1. Kod źródłowy można sobie zobaczyć i pobrać z katalogu python/quake w repozytorium kosciak-misc. Może komuś się jeszcze przyda.

Od strony programistycznej wielkiej filozofii tu w sumie nie ma. Całość sprowadza się do użycia modułu struct w celu rozpakowania danych binarnych. Jeśli zaś chodzi o samą strukturę danych najlepiej zerknąć do wspomnianych wyżej specyfikacji lub do źródeł narzędzia modelgen z pakietu qutils. Dodam jeszcze, że zaimplementowałem jedynie tzw "simple frames", nie uda się więc załadować modeli flame.mdl i flame2.mdl. Pozostałe wydają się działać prawidłowo.

A na koniec jeden z efektów zabawy z zaimportowanym modelem - stereoskopowy Shambler w galopie!

Shambler w galopie

Słyszałem, że wszystko wygląda lepiej w 3D :-)

19:43, kosciak1 , Dev
Link Dodaj komentarz »
czwartek, 06 stycznia 2011

Niedawno poproszony zostałem o pomoc w przygotowaniu fiszek (z ang. flashcards). Zadanie wydawałoby się proste, cóż może być trudnego w wygenerowaniu plików graficznych na podstawie listy słówek. Jak się okazało wcale nie było tak łatwo.

Python Imaging Library

Na początku postanowiłem sprawdzić najprostsze znane mi rozwiązanie. Postanowiłem użyć do renderowania tekstu PIL. Szybko napisałem prosty skrypcik by sprawdzić działanie biblioteki:

#!/usr/bin/env python
# -*- coding: utf-8 -*-

from PIL import Image, ImageDraw, ImageFont

WIDTH = 375
HEIGHT = 50

FOREGROUND = (0, 0, 0)
BACKGROUND = (255, 255, 255)

TEXT = 'zażółć gęślą jaźń'

font_path = '/usr/share/fonts/truetype/ttf-dejavu/DejaVuSans.ttf'
font = ImageFont.truetype(font_path, 32, encoding='unic')

text = TEXT.decode('utf-8')
(width, height) = font.getsize(text)
image = Image.new('RGBA', (WIDTH, HEIGHT), BACKGROUND)
draw = ImageDraw.Draw(image)
draw.text(((WIDTH - width)/2, (HEIGHT - height)/2), 
          text, 
          font=font, fill=FOREGROUND)
image.save('PIL_output.jpg')

A oto efekt:

Prawda, że ładnie? Wydawałoby się, że wszystko jest w najlepszym porządku - tekst wygenerowany, pliterki wyświetlone poprawnie, czego chcieć więcej. Nic tylko brać się za renderowanie słówek z listy. A tak, zapomniałem wspomnieć, że słówka są po... arabsku. Jeśli komuś się wydaje, że w XXI wieku, w erze Unicodu nie powinno być żadnych niech spojrzy na to:

Nawet jeśli ktoś nie zna arabskiego od razu zauważy, że coś tu jest nie tak. Frazę można przetłumaczyć jako odwrócony do góry nogami. A przynajmniej powinna to oznaczać, bo to co zostało wyrenderowane to jakaś zupełna sieczka... Trzeba było poszukać innego rozwiązania.

Pango i cairo

Po wieczorze poszukiwań znalazłem właściwe narzędzia: pango, Pycairo] i pangocairo. Oto prosty skrypt wykorzystujące te biblioteki:

#!/usr/bin/env python
# -*- coding: utf-8 -*-

import cairo, pango, pangocairo

WIDTH = 375
HEIGHT = 50

FOREGROUND = (0, 0, 0)
BACKGROUND = (255, 255, 255)

TEXT = 'zażółć gęślą jaźń'

font_description = pango.FontDescription('DejaVuSans 24')
surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, WIDTH, HEIGHT)
cairo_context = cairo.Context(surface)
pangocairo_context = pangocairo.CairoContext(cairo_context)

# layout settings
pango_layout = pangocairo_context.create_layout()
pango_layout.set_font_description(font_description)
pango_layout.set_alignment(pango.ALIGN_CENTER)
pango_layout.set_width(WIDTH*pango.SCALE)

# background
pangocairo_context.set_source_rgb(*BACKGROUND)
pangocairo_context.rectangle(0, 0, WIDTH, HEIGHT)
pangocairo_context.fill()

# render text
pangocairo_context.set_source_rgb(*FOREGROUND)
pango_layout.set_text(TEXT)
layout_width, layout_height = pango_layout.get_pixel_size()
ink, logical = pango_layout.get_pixel_extents()
pangocairo_context.move_to(0, HEIGHT/2 - logical[3]/2)
pangocairo_context.show_layout(pango_layout)

# write to file
surface.write_to_png('pangocairo_output.png')

Zobaczmy efekty:

No! I to mi się podoba! Trzeba napisać trochę więcej kodu, jednak możliwości są o wiele większe.

Powyższe przykłady można pobrać z mojego repozytorium.

20:29, kosciak1 , Dev
Link Komentarze (1) »
poniedziałek, 16 sierpnia 2010

Moja aplikacja Python Window Organizer (w skrócie PyWO) doczekała się nowej wersji!

Zmiany w PyWO 0.2

  • Zmiana licencji na GPLv3 - zauważyłem, że python-xlib, z którego korzystam udostępniony jest na GPLv2, więc nie pozostało nic innego jak zmienić licencję, na kompatybilną.
  • Możliwość wyłączenia poszczególnych funkcji z użyciem opcji ignore, zarówno globalnie (po umieszczeniu w sekcji [SETTINGS]), jak i dla poszczególnych sekcji definiujących siatkę.
  • Możliwość wgrania pliku z definicją siatki również z $HOME
  • Dwie nowe funkcje: Switch oraz Cycle.

Switch i Cycle

Funkcje te pozwalają na zamianę okien miejscami. Po naciśnięciu skrótu klawiaturowego (domyślnie Alt-KP_Divide i Alt-Shift-KP_Divide) wybieramy okno do zamiany. Możemy wybrać za pomocą Alt-Tab lub za pomocą myszy (aplikacja czeka na zmianę aktywnego okna). Jeśli chcemy anulować zamianę wystarczy jeszcze raz nacisnąć skrót odpowiedzialny za zamianę okien.

Switch

Zamiana okien miejscami

Następuje zamiana okien miejscami, przy czym dotychczasowe okno pozostaje aktywne.

Cycle

Zamiana zawartości okna

Następuje zamiana zawartości okien (po zamianie okien miejscami aktywne jest nowe okno, które teraz znajduje się na miejscu dotychczasowego).

17:54, kosciak1 , Dev
Link Dodaj komentarz »
środa, 11 sierpnia 2010

Dawno już tak długiej przerwy na blogu nie było... Już nawet miałem w głowie kilka pomysłów na wpisy o narzędziach ułatwiających zarządzanie oknami - Quicktile oraz wtyczkach Compiza: Grid, Put i Maximumize. Niestety stała się rzecz straszna. Zaczęły irytować mnie ich różne drobne błędy. Co gorsze, zdałem sobie sprawę, że żadna z tych aplikacji nie działa tak, jakbym chciał. Chyba już wiecie jak to się skończyło...

Python Window Organizer

W wolnym czasie, którego jak na złość za wiele nie było, zamiast pisać notki na bloga zgłębiałem tajniki EWMH, ICCM i Python X Library. Efektem tej pracy jest Python Window Organizer, w skrócie PyWO, prawdopodobnie najlepsze narzędzie wspomagające zarządzanie oknami.

Możliwości

Głównym założeniem jest umożliwienie łatwej zmiany położenia i rozmiaru okien okien z użyciem skrótów klawiaturowych (domyślnie sterowanie odbywa się z użyciem klawiatury numerycznej). Do dyspozycji mamy:

Float - przemieszczanie okien

Przemieszczanie okien

Możemy przesuwać okno w dowolnym kierunku, przyklejając je do krawędzi sąsiadujących okien.

Expand i Shrink - zmianę rozmiaru okna

Powiększanie i pomniejszanie

Możemy powiększać lub pomniejszać rozmiar okna w dowolnym kierunku, by maksymalnie wykorzystać dostępne miejsce.

Put - rzucanie oknem

Rzucanie oknem

Możemy rzucić okno (bez zmiany rozmiaru) w jedną z wcześniej zdefiniowanych pozycji na ekranie.

Grid - siatka

Siatka okien

Rzucamy oknem w wybraną pozycję na ekranie jednocześnie zmieniając rozmiar okna, w efekcie uzyskując siatkę, równomiernie rozłożonych okien. Można wybrać siatkę 2x2, 3x2 (domyślna), 3x3 lub łatwo zdefiniować własne ułożenie okien. Starałem się by ta funkcja działała bardziej przewidywalnie niż odpowiedniki w Compiz Grid i Quicktile - zawsze najpierw wybierany jest największy możliwy rozmiar.

Wymagania

Potrzebny nam będzie Python w wersji 2.5 lub wyższej (nie testowałem z 3.0) i zainstalowana biblioteka Xlib (w Ubuntu wystarczy zainstalować pakiet python-xlib). No i oczywiście menadżer okien poprawnie implementujący EWMH. Z pobieżnych testów wynika, że Python Window Organizer powinien działać z większością popularnych menadżerów okien. Testowałem w Compizie, Metacity, KDE (KWin), XFCE (Xfwin), Openbox, Enlightment (e16) oraz FVWM i wydaje się działać jak należy.

Jak na razie pod Blackbox, Fluxbox, IceWM, WindowMaker, AfterStep i pekwm pojawiają się dziwne błędy wynikające z niepełnego wsparcia dla EWMH przez te menadżery okien. Jest szansa, że część z tych problemów uda się obejść, jednak niczego obiecać na razie nie mogę.

Instalacja i użytkowanie

Wystarczy pobrać archiwum ze strony projektu PyWO, rozpakować i wykonać:

./pywo.py

Ot i cała filozofia. Skonfigurować do swoich potrzeb (zmiana klawiszy, siatki) można tworząc plik ~/.pyworc - opis jego składni i dostępnych opcji znajdziecie przeglądając dołączony plik pyworc, zawierający domyślne ustawienia.

Błędy, problemy i propozycje

Nie ukrywam, że jeszcze zostało trochę do poprawienie, zoptymalizowania. Jeszcze nie wszystko jest dostatecznie przetestowane. Nie wiem jak PyWO zachowuje się przy więcej niż jednym monitorze, wiem o problemach z oknami ustawionymi by pojawiały się na wszystkich pulpitach.

Jeśli zauważycie dziwne zachowanie prosiłbym, oprócz opisu niepożądanego zachowania, o przesłanie również pliku /tmp/PyWO.log, gdzie zapisywane są informacje o działaniu programu.

Chętnie też wysłucham waszych propozycji zmian. Dopóki zapał nie opadł jest spora szansa na ich realizację. Na pewno powinienem wkrótce dopisać funkcję Undo.

piątek, 21 maja 2010

Uwaga, uwaga! Nadjeżdża nowa, jeszcze lepsza, wersja TrollEyBuzza!

TrollEyBuzz - zmiany w wersji 0.2

TrollEyBuzz - klikamy!

Co się zmieniło w wersji 0.2?

  • Już nie trzeba niczego zmieniać w kodzie skryptu, wystarczy sobie wszystko wyklikać.
  • Jeśli zauważymy trolla klikamy w link Troll? (tuż obok Komentarz, Podoba mi się i E-mail) i wybieramy z listy osobnika, którego komentarze chcemy ukryć.
  • Jak w poprzednie wersji możemy w każdym momencie zobaczyć ukryty komentarz i ponownie go ukryć.
  • Tuż obok listy Obserwujących znajduje się licznik trolli, po kliknięciu pojawi się lista osobników, wystarczy jeden klik by osobę, która przestała trollować odblokować.

Instalacja bez zmian - potrzebny jest Firefox z Greasemonkey, a potem tylko klik w Install na stronie skryptu.

Niestety przy okazji urwało od wsparcia dla Chrome (GM_setValue i GM_getValue nie są tam zaimplementowane), polecam więc napisane dla tej przeglądarki rozszerzenie Buzz Troll Remover.

13:30, kosciak1 , Dev
Link Dodaj komentarz »
środa, 19 maja 2010

Muszę przyznać, że Google Buzz bardzo przypadł mi do gustu. Jest to po prostu znakomite miejsce do prowadzenia dyskusji. Niestety i tu potrafią przyplątać się różne internetowe trolle, które potrafią zakłócić każdą rozmowę. Jeśli taki osobnik zacznie nas obserwować, wystarczy delikwenta zablokować i nie będzie już mógł już dodawać swoich komentarzy. Gorzej jeśli jakiś wredny troll pojawi się u kogoś, kogo obserwujemy.

TrollEyBuzz - rozjedź trolla!

TrollEyBuzz i ukryty komentarz

Jednym ze skuteczniejszych sposobów obrony jest zwyczajne zagłodzenie trolla. Wystarczy nie komentować, nie dyskutować, nie reagować na zaczepki, całkowicie zignorować, mając nadzieję, że mu się znudzi i sam sobie pójdzie. Ale jak tu zachować spokój? Przecież palce aż świerzbią by coś takiemu odpisać...

Z pomocą przychodzi TrollEyBuzz - skrypt Greasemonkey, który ukrywa treść komentarzy pisanych przez trolla. Wystarczy skopiować adres profilu niegrzecznego dyskutanta i dodać go do listy trolli. Po ponownym załadowaniu Buzza niechcianych komentarzy już nie zobaczymy. Gdybyśmy jednak bardzo chcieli zobaczyć usunięty komentarz zawsze możemy kliknąć w [...], jednak nie ma co sobie psuć nerwów i podnosić ciśnienia. Jeśli przypadkiem rozwiniemy komentarz trolla możemy szybko kliknąć w [hide], by ponownie go ukryć.

Skrypt ten jest swego rodzaju odpowiedzią na Buzz Troll Remover - rozszerzenie dla Chrome napisane przez Przemelka.

Instalacja

Dla posiadaczy Firefoxa:

  1. Instalujemy Greasemonkey
  2. Wchodzimy na stronę skryptu TrollEyBuzz
  3. Klikamy w wielki przycisk "Install"
  4. Uruchamiamy menu NarzędziaGreasemonkeyZarządzaj skryptami, wyszukujemy na liście "TrollEyBuzz" i klikamy edytuj
  5. Zmienna TROLLS zawiera listę osób do blokowania. Wystarczy w Buzzie kliknąć prawym przyciskiem myszy na imię trolla, skopiować URL i dodać go do listy. Oto przykład listy blokowanych trolli:
    var TROLLS = [
    'http://www.google.com/profiles/brzydkitroll#buzz',
    'http://www.google.com/profiles/123456789012345678901#buzz',
    ];

UWAGA! W wersji 0.2 już nie trzeba nic zmieniać w kodzie skryptu!

Skrypt działa jedynie dla Buzza wbudowanego w Gmail. Na stronie profilu komentarze trolli nadal będą widoczne.

TrollEyBuzz działa również pod Chrome - wystarczy go zainstalować jako rozszerzenie (jednak zmiana listy trolli jest wtedy dość utrudniona, lepiej skorzystać z Buzz Troll Remover). Użytkownicy innych przeglądarek muszą poradzić sobie sami.

Changelog:

wtorek, 11 maja 2010

Wybór odpowiedniego narzędzia do publikowania notek na blogu to poszukiwanie kompromisu między kontrolą, a wygodą. Z jednej strony mamy edycję czystego kodu HTML, jednak wizja martwienia się o domykanie tagów, zamiast o treść wpisu (który staje się zupełnie nieczytelny) jakoś do mnie nie przemawia. Z drugiej strony jest edytor WYSIWYG, który ułatwia pisanie, o ile nie chcemy zrobić czegoś bardziej nietypowego (ileż czasu muszę poświęcić na ręczne dodawanie znaczników <code> w bardziej technicznych wpisach...). Czy jest dostępna jakaś trzecia droga?

KoMar - prosty wiki markup

KoMar markup w akcji

Rozwiązaniem jest użycie tzw. wikitekstu, pozwala to na pracę na zwykłym tekście (możemy więc użyć naszego ulubionego edytora), w który wplatamy proste w użyciu znaczniki. Tylko, czego konkretnie użyć? Textile, ani Markdown jakoś mnie do siebie nie przekonały. Zdecydowałem się zabrać sprawy w swoje ręce.

W efekcie powstał KoMar - prosty wiki markup, silnie inspirowany Creole 1.0. Główne cele to:

  • prostota użycia - składnia musi być naturalna, łatwa do zapamiętania i nie utrudniająca pisania tekstu.
  • czytelność - by mimo użycia dodatkowych znaczników tekst pozostał czytelny.
  • spójność - poszczególne elementy markupu muszą do siebie pasować.
  • wystarczająca ilość elementów - by nie trzeba było poprawiać wygenerowanego HTMLu, z drugiej strony nie wprowadzać zbyt wielu elementów.

Przy okazji chciałem się zmierzyć z problemem parsowania tekstu i trochę pobawić trochę bardziej rozbudowanymi wyrażeniami regularnymi.

Składnia

Do dyspozycji jest formatowanie tekstu:**wytłuszczenie**, //kursywa//, ~~przekreślenie~~, indeks ^^górny^^ oraz ,,dolny,,, jak i ``fragmenty kodu``. Można też określić ((---|wielkość)), ((++|tekstu)), jak i ((red/yellow|kolor)).

Odnośniki otaczamy [[ i ]], oddzielając opis za pomocą | na przykład [[http://kosciak.blox.pl/ | KosciaKowy blog]]. Podobnie z obrazkami, tyle że używamy {{ i }} a po | wpisujemy tekst alternatywny, na przykład {{/img/obrazek.png | Osadzony obrazek}}.

Paragrafy tworzone są automatycznie, oddzielamy je za pomocą pustego wiersza. Wstawiając na początku akapitu [>>], [<<], [><] i [<>] otrzymując odpowiednio wyrównanie do prawej, do lewej, wycentrowanie i wyjustowanie.

Listy tworzy się za pomocą znaków * i #, odpowiednio wcinając poziomy zagnieżdżenia listy, na przykład:

 * element pierwszy listy 
* element drugi
# zagnieżdżona lista wypunktowana
# drugi element listy wypunktowanej
* kontynuacja listy wyższego poziomu

By utworzyć nagłówki wystarczy poprzedzić linię znakami równości:

= Nagłówek 1 =
== Nagłówek 2
...
====== Nagłówek 6

Tekst preformatowany wystarczy otoczyć nawiasami klamrowymi {{{ i }}}. Bloki cytowanego tekstu poprzedzamy znakiem >, tak jak w przypadku pisania wiadomości e-mail. W bloku cytowanego tekstu możemy zagnieżdżać dowolne pozostałe elementy.

Co, gdzie, jak?

Dla osób, które chciałyby zobaczyć KoMara w akcji mogą przygotowałem parser działający online, gdzie można sobie testować do woli. Kod źródłowy parsera (napisanego w Pythonie), oraz plik tekstowy będący rozbudowanym przykładem można przeglądać i pobrać z repozytorium Subversion:

svn co http://kosciak-misc.googlecode.com/svn/python/komar/trunk/

Prace nad projektem KoMar nadal trwają. Muszę jeszcze zaimplementować kilka niezbędnych elementów (przede wszystkim kotwice, zagnieżdżanie plików wideo, oraz tabele), ale jak widać na przykładzie tej notki można już z niego z powodzeniem korzystać.

15:53, kosciak1 , Dev
Link Dodaj komentarz »
niedziela, 18 kwietnia 2010

W zeszłym tygodniu w Laboratorium Gmail pojawiła się nowa funkcja Zagnieżdżone etykiety (Nested Labels). Pozwala ona wyświetlać etykiety w formie drzewka, upodobniając je do drzewa folderów (wcześniej podobną funkcjonalność oferował skrypt Greasemonkey Folders4Gmail). Niestety domyślnie wszystkie etykiety są zwinięte. Jeśli ktoś jak ja ma zdefiniowanych kilkadziesiąt etykiet w formie rozbudowanego drzewa to może być problemem. Dlatego mając chwilę wolnego czasu napisałem skrypt rozwijający wybrane etykiety.

Zagnieżdżone etykiety

By uruchomić tą funkcję należy wejść do Ustawień Gmaila, przejść do Laboratorium (Labs) i włączyć Zagnieżdżone etykiety (Nested Labels). Następnym krokiem jest stworzenie odpowiedniej struktury etykiet. Poszczególne poziomy drzewa rozdzielamy za pomocą /. Musimy też pamiętać o utworzeniu etykiet dla wszystkich poziomów drzewa. I tak po utworzeniu etykiet Praca, Praca/Pilne, Praca/Klienci, Praca/Klienci/Nowak, Praca/Klienci/Kowalski otrzymamy takie oto drzewko:

Gmail - zagnieżdżone etykiety

W dodatku przy dostępie za pomocą protokołu IMAP również będziemy widzieć strukturę folderow.

Gmail - auto expand Nested Labels

Skrypt Gmail - auto expand Nested Labels automatycznie rozwija wybrane elementy drzewka zakładek po uruchomieniu Gmaila. Jeśli ktoś ma kilkanaście, kilkadziesiąt etykiet tworzących rzbudowaną strukturę ten wie, że ręczne rozwijanie drzewka jest bardzo denerwujące.

Instalacja

Dla posiadaczy Firefoxa:

  1. Instalujemy Greasemonkey
  2. Wchodzimy na stronę skryptu Gmail - auto expand Nested Labels
  3. Klikamy w wielki przycisk "Install"
  4. Uruchamiamy menu NarzędziaGreasemonkeyZarządzaj skryptami, wyszukujemy na liście "Gmail - auto expand Nested Labs" i klikamy edytuj
  5. Przypisujemy zmiennej autoExpand listę etykiet, które mają być automatycznie rozwijane. Należy pamiętać o odpowiedniej wielkości liter ('praca' i 'PRACA' to nie jest to samo), etykiety nadrzędne zostaną rozwinięte automatycznie. Przykład:
    var autoExpand = ['Praca/Klienci', 'powiadomienia'];

Skrypt działa zarówno dla zwykłego Gmaila, jak i dla poczty Gmail we własnej domenie.

Posiadacze innych przeglądarek muszą poradzić sobie sami. Pod Google Chrome nie chce działać symulowania kliknięcia. Nie wiem czy to problem z nieprawidłowym eventem, czy jakiś błąd wykonywania element.dispatchEvent(evt), jeśli ktoś zna rozwiązanie niech da znać.

Changelog:

  • 0.1.1 - poprawka po dzisiejszej zmianie w Gmailu
  • 0.1 - pierwsza wersja
15:32, kosciak1 , Dev
Link Komentarze (2) »
czwartek, 08 kwietnia 2010

Czytając o planowanej na dzisiaj przerwie technicznej Bloxa zdałem sobie sprawę, że nie mam na dysku kopii zapasowej bloga. Postanowiłem jakoś temu zaradzić. Dostępny jest ciekawie wyglądający program DeBergeraca pod tytułem Blex, jednak ze względu na użycie platformy .NET na Linuksie nie dane mi z niego skorzystać. Nie pozostało nic innego jak zerknąć do API Bloxa i napisać własne narzędzie.

Blox-exporter

Skrypt blox-exporter napisany jest w Pythonie i służy do pobierania i archiwizowania treści wpisów na blogach umieszczonych na platformie Blox.pl. Skrypt można pobrać z działu Downloads projektu (znaleźć tam można również skrypt dropbox-index), lub z repozytorium Subversion. Po ściągnięciu wystarczy skrypt uruchomić, zapytani zostaniemy o login i hasło do Bloxa, następnie musimy potwierdzić chęć pobrania naszych blogów. Pełna instrukcja obsługi wyświetli się po wywołaniu skryptu z --help

Po uruchomieniu w bieżącym katalogu utworzona zostanie struktura plików podobna do poniższej:

/nazwa_bloga
/2010
    /01
      /tytul_notki.html
  /index.html
  /resources.html

Plik index.html zawiera spis wszystkich wpisów (wraz ze szkicami) w kolejności chronologicznej. Plik resources.txt zawiera spis zasobów (wszystkie użyte obrazy i pliki z zasobów Blox linkowane we wpisach). By je pobrać polecam użycie programu wget. Wykonanie polecenia:

wget -i resources.txt -P resource

Spowoduje pobranie wszystkich wyszczególnionych w resources.txt plików do folderu /resource

Skrypt testowałem na Ubuntu z Pythonem 2.5 oraz na Windows z Pythonem 2.6. Niestety pod Windowsem są problemy z wyświetlaniem polskich znaków w konsoli i szczerze powiedziawszy na razie nie chce mi się szukać rozwiązania, te kilka "krzaczków" jakoś specjalnie nie powinno przeszkadzać.

Jeśli mi się będzie chciało (lub dostatecznie dużo osób wyrazi takie zapotrzebowanie) i znajdę trochę czasu to może w przyszłości dodam pobieranie tagów do notek, generowanie stron dla poszczególnych kategorii, eksport do BlogML i poprawię wygląd generowanych stron.

17:27, kosciak1 , Dev
Link Komentarze (6) »
poniedziałek, 29 marca 2010

Dotychczas wydawało się, że rozwiązaniem wszystkich problemów tego świata jest Cloud Computing. Niestety, gdy już przeniesiono do chmury wszystko co tylko się dało (oraz kilka rzeczy, których się nie dało) okazało się, że część problemów pozostała nierozwiązana. Tak oto nastała moda na NoSQL. Chyba każda rozsądnie myśląca osoba przyzna, że relacyjne bazy danych są takie wczorajsze, a nowe czasy wymagają nowych rozwiązań. Czy aby jednak na pewno? Bawiąc się trochę BigTable na Google AppEngine mam pewne wątpliwości.

Szybkość i skalowalność

Jeśli wierzyć zapewnieniom ewangelistów NoSQL użycie nierelacyjnej bazy danych sprawi, że nasza aplikacja znacząco przyśpieszy, problem skalowalności zostanie na zawsze rozwiązany i nie straszne nam będą miliony użytkowników. Niestety w rzeczywistości przeciętny startup o milionach, czy nawet tysiącach użytkowników może tylko sobie pomarzyć. Nie czarujmy się, problem skalowalności jest na początku problemem całkowicie abstrakcyjnym. Na pewno jest o wiele więcej poważniejszych spraw, którymi należy się zająć zamiast zastanawiać się, czy nasza aplikacja podoła obciążeniu rzędu tysiąca żądań na sekundę.

Warto też dodać, że nie każda aplikacja skorzysta na bazie nierelacyjnej. Z moich doświadczeń z BigTable wynika, że o ile odczyty z bazy są dosyć szybkie, tak zapis już niekoniecznie. Jeśli aplikacja wykonuje bardzo dużo zapisów do bazy danych zysk może być niewielki. W dodatku mogą się pojawić problemy ze spójnością danych, jeśli wystąpią problemy z replikacją danych pomiędzy serwerami (uroki działania w chmurze). A nawet w przypadku aplikacji głównie odczytujących dane z bazy często lepszy efekt daje intensywne cache'owanie wyników zapytań. Rodzaj bazy danych schodzi więc wtedy na drugi plan.

Baza wiedzy

Kolejna sprawa, o której wiele osób zapomina to fakt, że właściwy schemat bazy danych i optymalne zapytania same się nie napiszą. Pracując z SQLem wystarczy otworzyć dowolną książkę, pogadać ze znajomym fachowcem od baz danych i już wszystko wiemy. Cała, wypracowana przez lata wiedza jest w zasięgu ręki. W przypadku NoSQL musimy wyrzucić do kosza sporą część dotychczasowej wiedzy. Zmuszeni jesteśmy do poruszania się trochę po omacku, eksperymentując na każdym kroku. Nagle okazuje się, że to co działało znakomicie w świecie relacyjnym tu nie ma zastosowania lub jest bardzo niewydajne. Wiele z nowych rozwiązań dla osoby myślącej SQLem nie będzie wcale takie oczywiste, a część wyda się wręcz odrobinę szalona. Na przykład denormalizacja danych - w świecie baz nierelacyjnych nie jest niczym niezwykłym.

Ograniczenia, ograniczenia

No dobra, korzystając z baz NoSQL zyskujemy lepszą skalowalność, brak sztywnego schematu bazy danych, sporą elastyczność, mniej problemów z mapowaniem danych w bazie do obiektów zdefiniowanych w kodzie i pewnie jeszcze kilka rzeczy, o których nie mam pojęcia. Ale pojawiają się ograniczenia. Czasem bardzo istotne. Po pierwsze bazy NoSQL nie są relacyjne. Może i jest to oczywiste, ale chyba nie wszyscy tak do końca zdają sobie sprawę, co to tak na prawdę oznacza. Całą obsługę relacyjności pomiędzy danymi (jeśli jest nam potrzebna) trzeba emulować w kodzie aplikacji, na wbudowane w bazę danych rozwiązania nie ma co liczyć. Po drugie często brak JOINów. Oczywiście, można się obejść bez JOINów w zapytaniach ale wymaga to odpowiedniego przygotowania modeli danych. Po trzecie ograniczenia w składni zapytań. W przypadku BigTable na Google AppEngine mamy dosyć ograniczoną możliwość sortowania i filtrowania danych. Potrafi to bardzo utrudnić pisanie wydajnych zapytań, a przecież rozliczany jestem z każdej milisekundy pracy procesora.

Dojrzałość rozwiązania

Na koniec warto wspomnieć, że bazy NoSQL są najczęściej rozwiązaniami stosunkowo młodymi. Co za tym idzie daleko im do dojrzałości, a więc i niezawodności, rozwijanych od lat baz relacyjnych. Trzeba być gotowym na odkrywania nowych błędów, napotykanie się na problemy, z którymi nikt wcześniej się nie zetknął.

NoSQL - czy warto?

Wszystko zależy od tego co tak na prawdę nasza aplikacja ma robić. Nie wszystko nadaje się do działania w chmurze z nierelacyjną bazą danych. Trzeba też zadać sobie pytanie czy koszt nauki nowych nierelacyjnych rozwiązań, oraz sposobów na obejście ograniczeń, nie przewyższy zysków jakie bazy NoSQL mogą nam dać.

16:08, kosciak1 , Dev
Link Komentarze (3) »
 
1 , 2 , 3 , 4 , 5 ... 6
Spis Treści
Kanały RSS
Add to Google
Add to Netvibes