Pożegnanie taty

Black RibbonTen wpis jest całkowicie nietechniczny a związany z życiem prywatnym. Można nawet śmiało powiedzieć, że z życiem prywatnym każdego z nas – w mniejszym lub większym stopniu – ale jednak. Jeśli więc poszukujesz treści stricte technicznych, to nic takiego ciekawego tutaj się nie pojawi.

07.11.2019 byłem na pogrzebie taty i później postanowiłem popełnić krótki wpis z moimi przemyśleniami na facebookowej grupie „Jestem tatą”.
Po komentarzach i reakcjach członków tej grupy uznałem, że spotkał się z całkiem pozytywnym odzewem (wpis, chociaż tata chyba też) i pomyślałem, że może nie byłoby głupim pomysłem podzielić się nim w innej społeczności.

Czytaj dalej „Pożegnanie taty”

Fedora OSError libgdal.so undefined symbol GEOSMakeValid_r

Fedora Logo

Kilka dni temu nagle przestał mi się uruchamiać lokalnie projekt w Pythonie, rzucając nie do końca przyjemnym błędem: OSError: /usr/gdal30/lib/libgdal.so.26: undefined symbol: GEOSMakeValid_r. Pierwsze – z jakiegoś dziwnego powodu – co przyszło mi do głowy, to aktualizacja paczek Pythona. Ale nawet odtworzenie czystego venv-a nie rozwiązało problemu. Czytaj dalej „Fedora OSError libgdal.so undefined symbol GEOSMakeValid_r”

Zmiana rozdzielczości działania Xvfb na Travis CI

O ile uruchamianie „zwykłych” testów w ramach ciągłej integracji (Jenkins, Travis CI, Circle CI) raczej nie jest problematyczne – bo przecież uruchamiamy je tylko przeciwko konkretnym fragmentom kodu – to testy wymagające Xvfb (X virtual framebuffer) już takie oczywiste nie są.

Po zainstalowaniu Xvfb na Travisie powinien być dostępny plik konfiguracyjny tej usługi – /etc/systemd/system/xvfb.service. Jego zmiana  wymagać będzie sudo.
Warto sprawdzić, jaka rozdzielczość ustawiona jest domyślnie – u mnie było to 1024x768px – co w sumie w czasach obecnych bardziej pokrywa się z urządzeniami mobilnymi i błędnie założyłem, że Travis będzie operował na wyższej rozdzielczości – no bo przecież mamy XXI wiek.
W samych testach, mimo wymuszania maksymalizacji okna otwartej przeglądarki – niektóre testy kończyły się niepowodzeniem. Okazało się, że problemem jest właśnie rozdzielczość ekranu, a nawet zmaksymalizowane okno było na tyle małe, że strona wyświetlana była jak na urządzeniach mobilnych, przez co pewne elementy strony nie były widoczne w ogóle albo wymagały wykonania dodatkowych akcji. Wyjaśnia to też, dlaczego lokalnie testy przechodziły bez zająknięcia.

Niemało stresu kosztowało mnie znalezienie sposobu na wymuszenie, aby xvfb uruchamiał okienka w większej rozdzielczości – gdy już udało się to rozgryźć – okazuje się to wyjątkowo banalne.

Jedyne co trzeba było wykonać, to zatrzymać usługę xvfb, poleceniem – na przykład sed – zmienić poprzednio ustawioną rozdzielczość na nową w pliku konfiguracyjnym usługi i ponownie uruchomić usługę, czyli:

Dodatkowo, Travis CI pozwala na zbieranie artefaktów ale  ograniczeni jesteśmy tylko do wysyłania tego do AWS, a dokładniej do S3 (przynajmniej w chwili obecnej) – debugowanie było z tego powodu mniej przyjemne. Robot Framework, w przypadku niepowodzenia robi zrzuty ekranu – rozdzielczość tych zrzutów ekranu możemy uzyskać poleceniem file selenium-screenshot-1.png – oczywiście, wymagać to będzie uruchomienia buildu w trybie debugowania i/lub dostępu do utworzonych wcześniej artefaktów.

Przy okazji kilka kolejnych wskazówek, które mogą się przydać w pracy z Travisem.

  1. Podczas uruchamiania buildu w trybie debugowania otrzymujemy polecenie, którego potrzebujemy, aby zalogować się do Travisa. Warto dodać parametr -o ConnectTimeout=0 do tego polecenia SSH, jak w poniższym przypadku:
    ssh -o ConnectTimeout=0 unique-id-xyz@to2.tmate.io
    Oczywiście, potrzebne to jest tylko wtedy, gdy nie mamy tego ustawionego na stałe w konfiguracji SSH.
    Po zalogowaniu będziemy mieć możliwość wykonywać polecenia ręcznie – analogicznie do automatycznego wykonywania kolejnych poleceń z pliku .travis.yml.
  2. Gdy już będziemy zalogowani – aby przyspieszyć pracę i wykonanie poszczegółnych grup poleceń które wiemy, że nie stanowią problemu, możemy korzystać z poleceń basha: travis_run_* – czyli travis_run_before_install, travis_run_install, travis_run_before_script, itd – do każdej sekcji z naszego pliku .travis.yml dodajemy po prostu prefix travis_run_ i powinny wykonać się wszystkie polecenia z tej sekcji.
  3. Ponieważ Travis w momencie napotkania błędu, przy włączonej – chyba nawet domyślnie – opcji fast_finish: true oraz błędów w linii poleceń – zamyka połączenie SSH – sugeruję, by w trakcie debugowania ustawić w Bashu set +e, zabezpieczy nas to przed przedwczesnym zakończeniem builda z wynikiem błędu (jeśli wpiszemy coś nieprawidłowo w linii poleceń) i będziemy mogli na spokojnie przyjrzeć się komunikatom zwróconym przez wywoływane programy.
  4. Próby ustawiania różnych (wyższych) rozdzielczości dawały dziwne rezultaty:
    1280×1024 px -> 1050×888 px
    1920×1080 px -> 945×944 px
    1680×1050 px -> 825×914 px
    czyli jak widać, największą szerokość zrzutu ekranu dała pierwsza rozdzielczość.
  5. Nie ma możliwości komunikacji z Travisem poprzez scp – więc próba przesłania artefaktów w ten sposób także się nie powiedzie (uwzględniając kwestie przekazywania agenta SSH).

Cały przykład można znaleźć na GitHub i bezpośrednio na Travisie, a przykładowy plik .travis.yml poniżej:

Jak odzyskać trochę czasu dzięki porządkom w telefonie

Nie tak dawno temu zdarzyło mi się wysłuchać krótkiego podcastu od Developer Tea w którym to autor – Jonathan Cutrell – przedstawia bardzo prostą metodę na odzyskanie drobnych porcji czasu poprzez wprowadzenie niewielkich zmian w telefonie (i w sumie w każdym używanym intensywnie urządzeniu).

Trzeba mieć świadomość jednak, że nie sprawi to nagle, że przybędzie nam 5 godzin do całej doby do wykorzystania na inne aktywności, ale jak to ma miejsce w przypadku wielu takich małych optymalizacji – ich połączenie może być już całkiem zauważalne – nie tylko z punktu widzenia oszczędności czasu ale i naszego samopoczucia.

Wbrew pozorom nie chodzi o tak banalne i oczywiste rady jak: odinstaluj gry, odinstaluj aplikacje społecznościowe oraz wyłącz wszelkie powiadomienia.

Ta prosta zmiana zamyka się w reorganizacji ikon aplikacji, z których korzystamy najczęściej.

Zazwyczaj po odblokowaniu telefonu na ekranie główny miałem: zdjęcie syna w centrum ekranu, widget zegara w górnej części ekranu i dookoła katalogi tematyczne: Finanse, Nauka, Google, …
Ogólnie, gdy potrzebowałem coś zrobić, to najczęściej wymagało to najpierw przypomnienia sobie lokalizacji katalogu na ekranie, otwarcie go – ponownie, zlokalizowanie konkretnej aplikacji i dopiero jej uruchomienie. O ile w katalogu „Finanse” było tylko kilka aplikacji (aplikacja banku, PayPal, moBILET, Monefy) to inne katalogi wymagały nierzadko przewijania.
Ogólnie pole do popisu było spore.

I tak: wszystkie katalogi zostały delikatnie mówiąc zaorane. Pozostały jedynie 2 katalogi w dolnej części ekranu i 2 przyciski – okrojone tylko do aplikacji używanych przeze mnie codziennie. Jak czegoś potrzebowałem raz w tygodniu po prostu wylatywało.

W tej chwili wygląda to i używa się tego dużo lepiej.
Od lewej jest to przycisk Połączenia. Wcześniej trzymałem tutaj katalog z Połączeniem, Wiadomościami i Kontaktami – ale zauważyłem, że tych ostatnich nie używam wystarczająco często.
Następnie jest przycisk wyświetlania wszystkich zainstalowanych aplikacji.
Później katalog z aplikacjami Aparat i Galeria – podejrzewam, że też mógłby wylecieć, ale jeszcze nie zdecydowałem.
Na szarym końcu – najbliżej kciuka – katalog z najczęściej używanymi aplikacjami – oczywiście jeszcze odpowiednio posortowany: Chrome, Podcast Addict, Todoist, aplikacja banku, eReader Prestigio, Business Calendar i kilka innych – w tym komunikatory.

Katalogi i aplikacje są przypięte na dole, więc widoczne są na każdym ekranie – nie tylko startowym. Drugi ekran to tylko 2 widgety: aktualna lista z Todoist i Brain Focus (do techniki pomodoro) i wspomniana wcześniej przypięta u dołu ekranu lista.

Spotkałem się też z opinią, że przeglądarka to także aplikacja rozpraszająca – źródło, więc można także rozważyć jej usunięcie z szybkiego dostępu.

Przy okazji różnych poszukiwań znalazłem przyjemny dla oka (po instalacji odpowiednich motywów i niewielkiej konfiguracji) i szybki CM Launcher.

Cały odcinek podcastu do odsłuchania (7 minut): One Super Simple Tactic to Regain Your Time

Wersje oryginalne i pirackie filmów

UWAGA: Poniżej wyrażone opinie są moimi osobistymi i każdy ma prawo się z nimi nie zgadzać. Jeśli tak właśnie jest i chcesz złożyć skargę – naciśnij krzyżyk zamykający przeglądarkę.

Jakub „Unknow” Mrugalski opublikował ciekawy film, w którym porusza temat legalności oprogramowania przytaczając niezbyt przyjemną sytuację z życia. Źródło: Facebook

Korzystając z tej okazji chciałbym przedstawić inny problem, ale który także dotyczy legalności – filmów.
Jako ofiara konsumpcyjnego stylu życia oraz (nauczony przez mojego dziadka) chomikowania wszystkiego co popadnie kupuję filmy na DVD. Chociażby dlatego, że kiedyś nie mogłem sobie finansowo na to pozwolić. A że były/są filmy do których często z żoną wracamy – znając je (filmy) i tak na pamięć – to miło je mieć. Poza tym, VHSy ciężko już odtwarzać a Internety ktoś może nagle wyłączyć.

Dlaczego jednak uważam, że wersje „kupione” na torrentach są lepsze?

Ponieważ nie są naszpikowane spotami reklamowymi.

Płacąc za oryginalny film na DVD – zanim w ogóle zacznę film oglądać muszę się nasłuchać (i naoglądać), że pobranie filmu z Internetu to kradzież (właśnie dlatego zainwestowałem w legalną wersję). Oczywiście gdyby tego było mało muszą się jeszcze znaleźć reklamy filmów, które za miesiąc pojawią się w kinie. Po co, grzecznie się spytam?!
Ja rozumiem, że kasa się musi zgadzać, ale czemu kosztem zniechęcania klientów do płacenia za rozrywkę?

Jeśli jednak chodzi o problem poruszany przez Jakuba w kwestiach korzystania z oprogramowania bez licencji (oczywiście w niektórych sytuacjach) to podpisuję się nogiema i rencyma pod kilkoma komentarzami do tego filmu – w skrócie –  korzystanie z wersji elektronicznej nie zmniejsza ilości danego produktu u dostawcy, jednak może znacznie zwiększać prawdopodobieństwo kupna tego oprogramowania w przyszłości.

PyCharm – jedna konfiguracja na wielu instancjach

Ponownie chciałbym pochwalić PyCharma – w sumie to wszystkie IDE od JetBrains.

Otóż narzędzie to pozwala nam na współdzielenie naszej ulubionej konfiguracji środowiska pomiędzy różnymi instancjami – jeśli używamy tego IDE w pracy i w domu to warto z tego skorzystać.
Oczywiście ma to też ten plus, że w przypadku kradzieży/zniszczenia możemy w całkiem prosty sposób odzyskać poprzednią konfigurację.

A sprawa jest całkiem prosta:

  1. Zakładamy nowe repozytorium, np. w serwisie GitHub (tak, może być też GitLab albo jakiekolwiek inne – ja lubię GitHub)
  2. W PyCharm wybieramy kolejno File > Settings Repository i ustawiamy konkretny Upstream URL na adres repozytorium
  3. Nadpisujemy zdalne (Overwrite Remote)
  4. To samo robimy na pozostałych instancjach nadpisując ustawienia lokalne (Overwrite Local)

Gdy już mamy zsynchronizowane, każda zmiana powinna być automatycznie pobierana z i wysyłana do repozytorium – jednak opcja Merge też w niektórych sytuacjach może się przydać 🙂

Wąż w stringach

Jednym z pierwszych typów danych o których uczymy się w ramach najróżniejszych kursów programowania jest typ łańcuchowy – często określany jako string. Nie bez powodu jest to jeden z najczęściej używanych w programowaniu typów. A dlaczego? Ponieważ jako ludzie głównie działamy na tekście: czytamy książki, piszemy listy, ostrzegamy o wysokim napięciu, opisujemy substancje chemiczne, gryzmolimy tagi na rozkładach jazdy (kto wracał komunikacją nocną i nie mógł odczytać rozkładu przez głupie tagi wie, że tego typu teksty są najmniej lubiane) – w dużym skrócie – tekstu używamy wszędzie.

Oczywiście ma to swoje konsekwencje -w programowaniu wykorzystujemy tekst aby wyświetlić cokolwiek na ekranie, do logowania aktualnego stanu aplikacji, gdy prosimy użytkownika o podanie informacji, przesyłamy informacje przez sieć.

Łańcuch znaków jest po prostu kolekcją… znaków. Mogą to być zarówno znaki drukowalne, jak np. litery alfabetu, cyfry czy znaki interpunkcyjne lub niedrukowalne – znaki o specjalnym znaczeniu – spacje, tabulacje, „dzwonek systemowy”.
Stringi mogą mieć długość od zera do… prawie rozmiaru pamięci zainstalowanej w komputerze. Oczywiście, mają tutaj jeszcze ogromne znaczenie inne czynniki – np. wersja Pythona czy architektura komputera, jednak dla codziennych zastosowań nie powinniśmy się tym aż tak bardzo przejmować. Gdybyśmy jednak chcieli zrobić kopię zapasową Internetu możemy w pewnym momencie zderzyć się z błędem MemoryError.

Długość (między innymi) łańcuchów określa się wbudowaną w Pythona funkcją len jednak należy mieć na uwadze, że ilość znaków, którą widzimy to nie zawsze rzeczywista długość łańcucha trzymana w pamięci. Posiłkując się StackOverflow:

Dla Pythona 2 wyniki są jeszcze bardziej zaskakujące (w odpowiedzi na StackOverflow został właśnie użyty Python 2).

Stringi w Pythonie możemy zapisywać w kodzie na kilka różnych sposobów:

Jednak wyświetlanie na ekranie prostych łańcuchów znaków może w pewnym momencie stać się dość nudne – na szczęście wynaleziono interpolację.

Interpolacja to wg Słownika Języka Polskiego: „wstawienie wyrazów, zwrotów, zdań do pierwotnego tekstu; też: takie wstawione wyrazy, zwroty, zdania”.
W naszej sytuacji chodzi o podstawienie wartości ze zmiennych w konkretne miejsca w łańcuchu znaków.
Przykładowo jeśli posiadamy szablon z informacją o uczniu i jego ocenie: "Cześć {imię i nazwisko ucznia}. Uzyskałeś {ilość punktów} punktów z egzaminu." to każde nasze wystąpienie {coś tam} będziemy mogli podmienić konkretnymi wartościami.
Do uzyskania konkretnego łańcucha znaków – z już podmienionymi wartościami możemy podejść (ponownie) na kilka sposobów – lepszych lub gorszych.
I tak na przykład, jednym z nich – niezbyt fajnym ani wygodnym – będzie po prostu łączenie łańcuchów znaków:

Nie da się chyba tego lubić. Przy okazji warto zwrócić uwagę, że pamiętać musimy o rzutowaniu na odpowiedni typ funkcją str albo zderzymy się z błędem TypeError.

Inny ciekawy (dla masochistów) sposób, to zapisanie wszystkiego jako lista i jej połączenie pustym łańcuchem:

Kod tak wspaniały, że aż oczy bolą… No dobra, są sytuacje, gdzie podobne podejście będzie akceptowalne, całkiem zwięzłe i czytelne… ale to nie jest ten przypadek.

Zmierzamy powoli w kierunku lepszego jutra – rozwiązanie dość popularne jeszcze do niedawna:

Plusem tego sposobu interpolowania łańcucha jest to, że korzysta on z wielu dostępnych specyfikatorów formatowania – co pozwala nam z kolei przyoszczędzić na jawnym konwertowaniu wartości zmiennych na łańcuchowy typ danych – musimy jednak zadbać o odpowiedni specyfikator w stringu.

Pierwszy z zalecanych (moim zdaniem) sposobów interpolowania to wykorzystanie metody format obiektu string:

Sposób ten jest tak fajny, że aż dorobił się własnej strony internetowej z najróżniejszymi przykładami.

Drugim zalecanym (znów, moim zdaniem) sposobem jest użycie tzw f-stringów – dostępnych niestety dopiero od Pythona 3.6:

Jeszcze innym sposobem interpolowania o którym warto wspomnieć jest użycie klasy Template z modułu string:

jednak nie spotykałem się z nim zbyt często – warto jednak wiedzieć, że coś takiego jest.

Więcej o samej interpolacji w Pythonie poczytać możemy w oficjalnych dokumentach PEP-0215PEP-0498, PEP-0501 oraz PEP-0502.

Dodatkowo, sam łańcuch znaków jako obiekt ma całkiem sporo metod pozwalających operować na danym łańcuchu, przytaczając kilka takich metod:

UWAGA: Wywołanie takiej metody na stringu nie powoduje jej zmiany w pamięci.

I tym oto sposobem przechodzimy do faktu, że łańcuchy znaków są niezmiennym typem danych (tzw. immutable). Cool. I co to znaczy?
W dużym skrócie chodzi o to, że jeśli zmienimy łańcuch znaków to zmieni się jego lokalizacja w pamięci – zostanie utworzony nowy, zmodyfikowany obiekt. Najlepiej zaobserwujemy to na przykładzie:

Dla wygody skorzystałem z wbudowanych funkcji hex i id.

Na koniec warto wspomnieć o dostarczanym ze standardową biblioteką Pythona modułem string, który głównie może okazać się przydatny jeśli będziemy potrzebowali kolekcji znaków: małych lub dużych liter, cyfr (także ósemkowych lub szesnastkowych) czy białych znaków, itp.

Dodatkowe źródła:
[1] A string of unexpected lengths
[2] Moduł string