Majówka

Dziwna to majówka i dziwny urlop. Jedno i drugie poszatkowane i pracowite. Pierwszą i najważniejszą rzeczą do załatwienia była – jak zwykle spóźniona – zmiana opon na letnie. Spojrzałem na felgi od zimówek i stwierdziłem, że warto je odświeżyć, bo trochę ruda zaczyna wychodzić. A skoro zakładam letnie, to najpierw letnie. Poszedłem na łatwiznę – spray czarny matowy, wyklejenie boku opony taśmą malarską, przetarcie drucianą szczotką i papierem ściernym. Jest powiedzenie, że gdy masz młotek, wszystko wygląda jak gwóźdź. Zmieniłbym na gdy masz spray, wszystko wygląda jak wymagające malowania. Faktem jest, że sprayem maluje się bardzo fajnie – łatwo i szybko. Niestety, przygotowanie felg zajmuje dłuższą chwilę. I oczywiście na jedną stronę z kół letnich zabrakło mi spray, a jak pojechałem dokupić w niedzielę, to okazało się, że sklep już zamknięty, więc w sumie zeszło znacznie dłużej, niż planowałem, więc odświeżone zostały tylko letnie. Zimówki i zapas muszą dłuższą chwilę poczekać.

Potem musiałem wrócić – tym razem pociągiem – do Poznania. Jedna sprawa do załatwienia, ale głównym powodem było złożenie PITa. Również tradycyjnie w ostatni dzień. Powody składania na papierze są różne – coś mi świta, że pod Linuksem nie szło to łatwo, trzeba mieć jakieś dodatkowe dane z poprzednich lat, a jakieś dziwne dodatki ostatnio jeszcze musiałem rozliczać. Głównie jednak chodzi o to, że papierowe mam przećwiczone, a nie chce mi się kombinować w ostatni dzień z nowym sposobem.

Oczywiście mogłem wysłać PIT pocztą, ale była jeszcze sprawa na miejscu, a stwierdziłem, że w pociągu sobie poczytam. Faktyczni, nadrobiłem lekturę i mam nadzieję, że wciągnę się z powrotem do czytania książek bo – wstyd się przyznać – to pierwsza przeczytana „moja” książka w tym roku. Nieco zasługa tego, że łapię się za cegły, niektóre nie podpasowują, a nie lubię brać się za kolejną książkę mając nieprzeczytaną inną.

Załatwiwszy temat opon, stwierdziłem, że zrobię lepszą składankę z muzą do auta. Do tej pory używałem uszkodzonej karty pochodzącej z Raspberry Pi (całkiem dobrze sobie radziła, ale w sumie nic dziwnego, to tylko odczyt, a uszkodzony jest IIRC konkretny fragment). Niestety, okazało się, że nowe utwory nie wejdą. Nie wiem czy to zaleta mtp[1], czy łapały się w uszkodzony obszar. Może kiedyś pobawię się w diagnostykę (ciekawe czy radio poradzi sobie z dwiema partycjami?), teraz po prostu pojechałem do sklepu i kupiłem nową. Oraz żarówkę do świateł pozycyjnych, w końcu. TBH wymieniłbym już dawno oryginalne W5W na stosowne LEDy, ale podobnoż się czepiają na przeglądach. Nie wiem czemu, w końcu i tak to praktycznie nie świeci, więc wolałbym, żeby przynajmniej prądu nie brało, przy zbliżonej jasności.

Tak naprawdę kupiłem dwie karty. Druga wylądowała w Raspberry Pi robiącym za router GSM. Tu słowo o stabilności Linuksa i rozwiązań chałupniczych (rpi + modem USB + hub USB), bo miałem niedawno okazję na ten temat rozmawiać. Albo raczej jeden uptime:

08:32:00 up 287 days, 18:42, 1 user, load average: 0.06, 0.08, 0.08

Głównym zasłużonym jest tu… prąd, bo router działa bez UPSa…

Kartę wymieniłem, bo chciałem zrobić upgrade Raspbiana – lada moment Debian Jessie przestanie być wspierany, a używany Raspbian właśnie na nim bazował. Poszedłem na łatwiznę i po prostu wrzuciłem najnowszy image,  bazujący na Stretch, dograłem brakujące pakiety i wrzuciłem kluczowe pliki z konfiguracją. Jestem nieco zaniepokojony, że taka rzeźba na szybko zaczyna mi wychodzić. Chyba muszę to na Githuba wrzucić. I może jakieś ansible do kompletu? W sumie rozjechała się tylko jedna rzecz – wyciąganie IP z interfejsu w jednym skrypcie. I tylko dlatego, że ifconfig zmienił format, więc automatyzacja i tak nic by tu nie pomogła…

Poza tym, sporo działki. Trochę pomogłem rodzicom na działce, trochę odpocząłem. Generalnie raczej pracowicie, choć i tak wielu rzeczy nie udało się zrobić, jak np. porządków z przekierowaniem ruchu ze starego bloga. Ale to może jeszcze w weekend ogarnę.

[1] Korzystałem z telefonu, bo okazało się, że nie bardzo mam czytnik kart micro SD – muszę kupić jakiś tani badziew i niech leży na takie okazje, bo wyciąganie modemu USB to nie jest to, co tygrysy lubią najbardziej.

Przerwa majowa

Uważni czytelnicy dostrzegli, że w zeszłym tygodniu nie pojawił się żaden wpis. Regulamin DSP2017 dopuszcza przerwy w prowadzeniu projektów i… zeszły tydzień należy potraktować jako przerwę. Zresztą ponad tydzień, bo w zasadzie majówka cała nieprojektowa, z małym wyjątkiem, o którym zaraz. W każdym razie z konkursu się nie wycofałem i mam nadzieję, że tygodni roboczych będzie wystarczająco dużo. Nie liczyłem ile jest dokładnie, a zarejestrowałem się z opóźnieniem. Tak czy inaczej, nie chodzi o to by złowić króliczka…

Przerwy są dobre, czy to w pracy jako urlop, czy przy projekcie. Można spojrzeć z boku, wyskoczyć z utartych torów i nabrać energii. W każdym razie zeszły tydzień był mocno pracowity, a wypełnianie PITów, to nie jest coś, co warto odkładać na ostatnią chwilę, powiadam wam. Zresztą warto wcześniej sprawdzić, czy ma się komplet papierów, jak się okazuje. W każdym razie zdobyłem kolejny skill w zakresie obsługi podatków. Ale ostatecznie wszystko w miarę wyprostowane.

Potem był czas dobrych imprez i intensywnego chodzenia po sklepach celem urządzenia oświetlenia – powiedzmy, że 20% zrobione. A w międzyczasie doglądanie zewnętrznych rzeczy – a to serwer się zaczął restartować bez przyczyny (odpowiedź ISP rozwaliła, ale restarty ustały, hm…), a to ktoś zepsuł format danych, z których korzystam… Chwilę trwało, zanim przyswoili, że błąd zgłasza osoba z zewnątrz, a nie pracownik. Fun, fun, fun. Tylko czasu szkoda.

Udało mi się zrobić dwie związane z projektem rzeczy: przetestować uruchomienie programu na czystym systemie z ARM (działa, czemu miałby nie działać?) oraz wstawić Raspberry Pi zamiast Banana Pi jako router, czyli odzyskać właściwą sondę. Co prawda to ostatnie nie udało się w 100%, bo robiłem na szybko, trochę czasu zeszło na ustalenie, że NAT lepiej działa, jak się włączy forwarding, a po wszystkim okazało się, że logowanie przy pomocy autossh coś nie działa, ale powiedzmy, że wariant minimum jest zrobiony. Z powodu małej ilości czasu nie zaryzykowałem też wpięcia drugiego modemu.

Przerwa i programowanie w pracy skłoniło ku refleksji, że może jednak lepiej będzie docelowo przepisać to obiektowo. Głównie chodzi o łatwość wykorzystania kodu w innych projektach – dokładnie to przerabiam w pracy. W cele projektu oficjalnie tego nie wpisuję póki co, ale jeśli tylko starczy czasu, to będzie próba refaktoringu kodu.

Python

Tak się składa, że ostatnio podstawowym językiem programowania, którego używam, jest Python. W związku z tym kilka przemyśleń na jego temat i na temat rozpoczynania zabawy z nim. Disclaimer: do Pythona podchodziłem już kiedyś, jeśli muszę coś napisać, to domyślnie korzystam z Perla. Niekoniecznie pięknego, często poganiającego polecenia systemowe, ale działającego. Historycznie bawiłem się Pascalem, C i oczywiście miałem kontakt z Bashem i PHP (do ostatniego oficjalnie się nie przyznaję).

Po pierwsze, istnieją czytelne reguły, np. PEP 8, którego wszyscy używają[1] czy PEP 20. Są też narzędzia, które ułatwiają zachowanie zasad dotyczących formatowania kodu, aby był zgodny z wytycznymi. Nie sposób tu nie wspomnieć o edytorze Atom, którego kiedyś włączyłem i wydał mi się straszną kobyłą. Jednak w połączeniu z pluginami działa naprawdę dobrze. Na tyle na ile mogę stwierdzić przy tak małym doświadczeniu. W każdym razie ma wszystko, do czego używałem kate. I sporo więcej. Vim nigdy mi nie podszedł na tyle, bym go używał w bardziej zaawansowany sposób. Do szybkich poprawek zawsze było albo nano, albo właśnie vim. Ale tryb tekstowy to nie jest to, co preferuję przy pracy nad dłuższym kodem.

Po drugie, dostępnych jest dużo materiałów do nauki Pythona. Także bezpłatnych. Samych książek/kursów jest kilkanaście (choćby oficjalny The Hitchhiker’s Guide to Python). Istnieją też gry, które uczą programować w Pythonie. Choćby Codecombat, którym kiedyś się bawiłem, o którym miała być notka, ale które ostatecznie mnie nie wciągnęło, a pomysł na notkę jakoś się rozmył. Mi do gustu przypadł jednak interaktywny kurs Learn Python na Androida. Jednak jeśli coś piszę i są interaktywne testy, a nie tylko czytam, to zapamiętuję więcej. Oczywiście nawet jeśli zapamiętam to do poziomu „potrafię użyć w programie” jest jeszcze kawałek, ale przynajmniej rozumiem przykłady i gotowy kod.

Po trzecie, istnieje sporo gotowych modułów, które ułatwiają pisanie. Jednak nawet gdyby nie istniały, to kod można „pożyczać” z innych skryptów przy pomocy import. I można mieć różne wersje bibliotek za sprawą środowisk wirtualnych. Z jednej strony fajne, z drugiej tworzy bałagan. Do developerki przydatne i zgodne z modną ostatnio ideą konteneryzacji. Ogólnie nauczyłem się z tym żyć, ale odruchu, żeby wszystko robić w virutalenv jeszcze nie mam.

Skoro mowa o bałaganie, to pora na wady, a tych jest zaskakująco wiele. Po pierwsze, Python 2 nadal żyje, ma się dobrze i można go spotkać na wolności. Taka umowna wada i na razie nie bardzo przeszkadza. Niemniej, nie każdy kod napisany w Pythonie 3 daje się wykorzystać w wersji drugiej.

Inna trochę dziwna na początku rzecz, to struktury danych. Jest tablica (list, w Perlu array), jest tablica asocjacyjna (dict, w Perlu hash). Ale są też tuple (niemodyfikowalne listy) i sety (nieuporządkowane zbiory unikatowych wartości). Nie żebym nie widział zalet, ale żeby aż wydzielać to? Zwł. sety (normalnie to po prostu się hasha tworzy, klucze są nieuporządkowane i unikatowe)…

To co się najbardziej rzuca w oczy: wcięcia. Są wymagane i rzutują na kod. Najprostszy przykład to:

for i in range (3):
    print ("wartosc: ")
    print (i)

Usunięcie wcięcia w ostatnim wierszu totalnie zmieni sposób działania programu. Drażni szczególnie na początku, gdy chcemy coś na szybko przetestować i np. coś wklejamy. Trzeba poprawić i dokładnie sprawdzić wcięcia, inaczej mogą być kwiatki jak wyżej.

Kolejna rzecz, która irytuje, to wciskanie filozofii w stylu zen. Na siłę i niekoniecznie zgodnie z prawdą. Weźmy mój ulubiony przykład:

There should be one– and preferably only one –obvious way to do it.

No to teraz bierzemy na tapetę set. Można go utworzyć przez

mojset = set([1, 2, 3])

Ale od wersji 2.7 można użyć do tworzenia równoważnej formy

mojset = {1, 2, 3}

Nie ma problemu? No to jak utworzyć pustego seta? Gdyby ktoś wpadł na całkiem logiczny pomysł użycia

mojset = {}

to niech wie, że nie pustego seta stworzył, a pustego dicta i za chwilę dostanie błędem po oczach. BTDT, dobry kwadrans dumania, czemu to nie działa. Dopiero wezwana pomoc uratowała sytuację, bo nie wiem ile bym jeszcze nad tym dumał.

Także one way my ass, skoro Tim Toady wita nas już na samym wstępie, przy tworzeniu jednego z podstawowych typów danych.

Możliwe, że dla ludzi, którzy zaczynają programowanie od Pythona, wady nie są tak zauważalne czy irytujące.

Niemniej, oddaję sprawiedliwość – w Pythonie pisze się przyjemnie i w praktyce jest to łatwiejsze, niż wygląda na pierwszy rzut oka. Wystarczy przejrzeć jakiś tutorial. Zdarzało mi się pisać rozszerzenia do istniejących skryptów po kilku dniach styczności z językiem i nie było większych problemów. Więc faktycznie, może być czytelnie, prosto i wygodnie. Oczywiście mogło być tak, że na ładne skrypty trafiłem. 😉

Z Perlem oczywiście nie kończę, bo do pewnych rzeczy nadaje się IMHO lepiej. Trochę gratów mam w nim napisanych, ale wersji 6 raczej już nie zacznę.

[1] A przynajmniej prawie wszyscy. A przynajmniej starają się. Prawie wszyscy.

UPDATE: Wspomniany kurs Learn Python skończyłem i szczerze polecam. Świetna podstawka, traktująca szeroko o różnych zagadnieniach, przy czym, jednak, te praktyczne części są lepsze, a teoretyczne kuleją. Jest w sumie o wszystkim najważniejszym, z programowaniem obiektowym i regexpami włącznie. Zapomniałem też wspomnieć o ipython – bardzo fajny do szybkiego sprawdzenia jakichś drobiazgów.

Swoją drogą, dziwi mnie to wciskanie regexpów do nauki programowania. To jest IMHO osobna działka zupełnie i nijak się nie klei z resztą.

Przy okazji kolejny kamyczek do ogródka w Pythonie jest inaczej. Tym razem chodzi o re.match, które działa totalnie nieintuicyjnie, choć przyznaję, że w sposób zgodny z dokumentacją. Otóż ww. funkcja dopasowuje wyrażenie tylko na początku stringa. Czyli ma takie niejawne, hardcodowane ^ – i albo .* na początku, albo korzystamy z re.search, żeby było normalnie. One way my ass, ponownie. Szczęśliwie wyszło to na Learn Python, nie w praktyce. Nie wiem co za piękny umysł to wymyślił i w imię czego…