Echo w rurach i WC. Program konsolowy od podstaw

ciemnastrona.com.pl 3 dni temu
Zdjęcie: Okno konsoli widoczne na pierwszym planie, w które wpisane są słowa 'Wpis numer 100', pionowa kreska i słowo 'wc'. W tle widać plątaninę generowanych losowo rur.


Po kilku latach jest i on – okrągły wpis numer 100 na stronie głównej bloga :smile:

Zastanawiałem się, którą z rzeczy z wirtualnej szuflady powinienem z tej okazji dokończyć.
„Niespiskową teorię świata” z ogólnymi przemyśleniami na temat korupcji i współczesnego kolonializmu? Wpis o największej branżowej akcji dezinformacyjnej, z jaką się spotkałem? O potencjale śledzącym akcelerometru? Może coś o ciemnych stronach Play Store’a?

Ale ostatecznie uznałem, iż nie ma co się spinać. Okrągła liczba ma znaczenie chyba tylko dla mnie, bo raczej mało kto czyta bloga liniowo. A zatem: zamiast wielkich, smoczych spraw będzie wpis luźniejszy, który bawi i uczy. A zamiast smoczego ognia będzie woda, bo niedawno było o niej głośno. Jak nie powódź w Polsce, to w Hiszpanii.

A jak woda, to rury. Przybliżę, intuicyjnie i na schematach, rury w konsoli systemu Linux, pozwalające „przelewać” dane z jednego programu do drugiego. Krok po kroku stworzę też drobny skrypt w języku Python, po każdej poprawce coraz lepiej zintegrowany z systemem.

Zapraszam! Również osoby mniej konsolowe, żeby się oswajały :smile:

Źródła: kultowy wygaszacz ekranu, konsola systemu Linux Mint. Przeróbki moje.

Uwaga o systemach

Wpis stworzyłem z myślą o systemie Linux Mint. Te same programiki działają na zwykłym, niemodyfikowanym telefonie z Androidem (wewnątrz apki Termux).
Nie testowałem ich natomiast na systemie Windows. Ale, z tego co zerknąłem, w windowsowej konsoli PowerShell można znaleźć program echo, a także rury, zaś odpowiednikiem wc wydaje się Measure-Object.
A zatem: jeżeli ktoś ma Windowsa, ale też się chce pobawić, to zapraszam! Ale nie gwarantuję, iż będzie śmigało.

Spis treści

  • Wprowadzenie
  • WC i inne mikroprogramy
  • Konstrukcja własnego programu
    • Przyjmowanie i wyrzucanie tekstu
    • Problem pierwszy: niewykonywalność
    • Problem drugi: niewskazanie Pythona
    • Ulepszenie: magiczna linijka
    • Ulepszenie: wzywanie z dowolnego miejsca
  • Podsumowanie
  • Bonus: możliwe modyfikacje

Wprowadzenie

Choć postronnym konsola może kojarzyć się z hakerstwem i jakimśtam stopniem wtajemniczenia, tak naprawdę można się z nią spotkać w całkiem codziennych i prozaicznych sytuacjach.

Ot na przykład: nie pamiętam, jaką mam w laptopie kartę graficzną i chcę to sobie sprawdzić. A zatem wpisuję w zwykłą internetową wyszukiwarkę: linux how to check graphics card. Wyskakuje mi jakaś stronka, być może ta. A tam krótkie polecenie, które powinno rozwiązać moje problemy:

lspci | grep VGA

Jego objaśnienie za parę akapitów.

Dla jasności: bardzo możliwe, iż te same informacje byłyby do wyklikania w jakimś najzwyklejszym, graficznym menu. To mit, iż używanie Linuksa wymaga znajomości konsoli. Zresztą choćby w podlinkowanym artykule jest opisany sposób oparty na klikaniu myszką.

Sposób konsolowy ma natomiast wielką, ogromną zaletę – jest uniwersalny. Powinien zadziałać wszędzie, na każdej z wielu odmian (dystrybucji) Linuksa. Nawiązując do konsoli, autor artykułu trafia do szerszego grona, niż gdyby pisał o jednej nakładce graficznej.

Inną zaletą jest szybkość i prostota. Wystarczy po prostu skopiować podany tekst, uruchomić konsolę (przez ikonkę z dolnego paska albo kombinację klawiszy Ctrl+Alt+T), wkleić komendę i nacisnąć Enter. I zrobione, wyświetli się szukana nazwa karty graficznej.

Uniwersalność metody konsolowej wynika z tego, iż system często zawiera zestaw domyślnie zainstalowanych programów, prostych i niezawodnych. Jak tutaj: lspci od wypisywania informacji o częściach komputera, grep od wyszukiwania konkretnego tekstu (tu akurat: VGA, bo taki jest przy karcie graficznej).
Takie małe programiki są zgodne z tak zwaną filozofią uniksową (od systemu Unix, praprzodka wielu współczesnych systemów) – „rób jedną prostą rzecz, ale rób ją dobrze”. Aprobuję.

Jeszcze ważniejszą rzeczą od programów jest natomiast pomost między nimi – |, czyli po angielsku pipe operator, inaczej pipe. W dosłownym tłumaczeniu: „rura”.

To element często stosowany w konsoli. Pozwala przekazywać to, co wypluje program po jego lewej stronie do programu po prawej. Łączyć mikroprogramy w rozwiązywacze codziennych problemów.
A iż Linux ceni wolność, to nie jesteśmy ograniczeni do programików z zamkniętej, narzuconej odgórnie listy; trzymając się paru zasad, można tworzyć również własne skrypty, w pełni pasujące do wszelkich rurociągów. Co za chwilę uczynię.

Ale do tanga rury trzeba dwojga, więc przyda się jakiś program, z którym fajnie by się zintegrował ten mój skrypt, który dopiero powstanie. Który z wielu domyślnych by tutaj wybrać?
Jestem prostym człowiekiem. Jak rury, to woda. Jak woda, to WC.

WC i inne mikroprogramy

Choć nazwa programiku konsolowego wc może budzić uśmiech, to tak naprawdę skrót od word count. „Liczarka słów”. A także linijek i znaków (z pewnym zastrzeżeniem, o którym za sekundę). Fajne narzędzie pozwalające na przykład się rozeznać, jak duże są różne nasze pliki.

Wrzucę do tej liczarki jakiś tekst na próbę, podając go rurą. Musi być otoczony cudzysłowami, żeby spacje nie miały dla konsoli specjalnego znaczenia. Pierwsza myśl:

'Jakiś tekst' | wc

…Ale to nie zadziała, bo tekst „luzem”, nieprzywiązany do niczego, nie jest tolerowany przez konsolę. Trzeba go „przemycić” wewnątrz jakiegoś programu czy zmiennej. Sposobów jest wiele, ale chwycę się najprostszego. Można wprowadzić tekst do konsoli programem echo:

echo 'Jakiś tekst' | wc

Takie polecenie już zadziała, tekst trafi do liczarki i wyświetlą się trzy liczby: 1 2 13. liczba linijek, liczba słów i liczba… znaków? Tyle iż z ostatnią coś się nie zgadza, o czym za sekundę. Ale najpierw drobny schemat:

Wybaczcie mi kloaczny humor.
Źródła: Flaticon – czerwona i zielona strzałka od Creative Stall Premium, maszynka do mięsa, toaleta i rura od Freepik. Przeróbki moje.

Odnośnie liczby, która się nie zgadza: wyraźnie mamy 5 liter w pierwszym słowie, 5 w drugim, jedną spację. Łącznie 11 znaków, a pokazuje 13.

Jedna nadwyżkowa rzecz bierze się stąd, iż echo domyślnie dodaje na końcu wprowadzonego tekstu znak kończący linijkę. W wielu kontekstach jest on umownie zapisywany jako \n, ale jego długość wynosi 1.
Można go sobie wyobrazić jak oznaczenie niewidoczne gołym okiem, ale bez wątpienia obecne w danych. Jak znaczek , który Word czy LibreOffice dodają w trybie wyświetlania znaków specjalnych.

To wyjaśnia rozbieżność o 1, ale skąd przesunięcie numer 2? Mówiąc prosto – wc liczby bajty, a nie widoczne znaki. Żeby nie siać zamętu, zignoruję ten fakt i odtąd będę wrzucał do konsoli tylko podstawowe znaki i litery. A szczegóły pozostawię osobom chętnym.

Szczegóły (dla chętnych)

Druga nadwyżka wynika z obecności polskiego ś, które za kulisami jest złożone z dwóch bajtów danych. W przeciwieństwie do podstawowych znaków angielskiego alfabetu, które są jednobajtowe. Polskie znaki to i tak pikuś – emoty (zwłaszcza flagi krajów) są jeszcze cięższe.

Ogólniej, chcąc dokładniej zbadać, co tam echo przyniosło, możemy użyć prostego sposobu z forum StackOverflow. Korzystając zz niezawodnej rury, wrzucić tekst do programiku od:

echo 'Jakiś tekst' | od -c

Pokaże nam wtedy, z czego się on składał:

0000000 J a k i 305 233 t e k s t \n

Gdyby zamiast ś użyć litery s, a do Echa dopisać po spacji argument -n (nakaz, żeby nie dodawało znaku końca linii), to liczba na końcu wyniesie oczekiwane 11.

Koniec bonusowego objaśnienia.

I na koniec, żeby wc nie jawił się jako zabaweczka, pokażę jedno jego praktyczne zastosowanie w kombinacji z innym mikroprogramem. Będzie to liczenie elementów w dowolnym folderze, wykonane w duecie z programem ls:

ls | wc

Działa to w ten sposób, iż programik ls, wypisujący nazwy rzeczy (plików/folderów…) zawartych w aktywnym folderze, wypluwa po jednej rzeczy na linijkę. Gdy do wc przerzuci się te wszystkie linijki, to ich liczba siłą rzeczy będzie równa liczbie rzeczy w folderze.

Można też napisać wc -l, żeby pokazało jedynie liczbę linijek.

Konstrukcja własnego programu

Przedstawiłem cegiełki, więc teraz czas z nich coś zbudować.

Skoro już mamy rury i WC, to przyda się coś również nawiązującego do motywu wody. Dlatego swój mikroprogram nazwę zbiornik. I niech działa podobnie jak zbiorniki retencyjne – zatrzymuje część lecących danych. jeżeli ich ilość będzie większa niż jego pojemność, to reszta danych się „przeleje” i poleci dalej.
Programik ten docelowo ustawię między echo a wc.

To do dzieła! Stworzyłem sobie plik o nazwie zbiornik (na Linuksie nie ma problemów, jeżeli nie dopiszę końcówki .py, typowej dla skryptów Pythona). A teraz co do niego wpisać?

Przyjmowanie i wyrzucanie tekstu

Ta część jest napisana w Pythonie, ale nie zrażajcie się, jeżeli go nie znacie; można wziąć na wiarę, iż działa, i przejść do dalszych spraw wokół rur.

Skoro chcę stawiać swój zbiornik na drodze lecących danych, to siłą rzeczy musi mieć jakiś wlot i wylot. W jaki sposób mogę sprawić, żeby:

  1. przyjął to, co wypluł program przed nim,
  2. podał dalej coś innego?

Przydaje się tu szczypta terminologii. To, co wpada – do programów i nie tylko – to w światku komputerowym input. Rzeczy wypadające to output. Wiedząc to, mogłem powierzyć wyszukiwarce DuckDuckGo swój problem: python accepting console input output. I niezawodny Stack pokazał rozwiązanie:

import sys for stream in sys.stdin: # W tym miejscu mogę coś zrobić sys.stdout.write( stream )
Objaśnienie (kliknij, żeby rozwinąć).

Moduł sys jest domyślnie zawarty w Pythonie i pozwala na integrację z różnymi systemowymi rzeczami, ale trzeba go importować, żeby skorzystać z jego możliwości;
sys.stdin pozwala sięgać po dane wpadające wejściem standardowym (czyli zwykle rurą);
wpadają one linijka po linijce, więc też obrabiam je po kolei, w pętli for;
stream to nazwa umowna (mogłaby być inna), tymczasowa, dla każdej z wpadających rzeczy;
na końcu jest obiekt sys.stdout, który ma swoją funkcję write, wyrzucającą dane z powrotem do „świata konsolowego”.

Linijkę „(…) coś zrobić” z komentarza wyżej zastąpiłem kodem, który ucina część wpadających danych (w praktyce: bajtów). Uznałem, iż będzie to zawsze 5 pierwszych rzeczy. Taki mikrozbiornik. Może politykom nie chciało się zanadto przeznaczać nań budżetu.

import sys empty_space = 5 for stream in sys.stdin: stream = stream[empty_space:] empty_space = max(0, empty_space - len(stream)) if stream: sys.stdout.write( stream )
Omówienie (kliknij, żeby rozwinąć)

Pojemność zbiornika empty_space powinna być resetowana przy każdym uruchomieniu skryptu, ale nie między napływem linijek. Dlatego umieszczam ją powyżej pętli.
Przy pierwszej napływającej linijce ignoruję pięć elementów na początku, od 0 do 4 (listy Pythona są numerowane od zera). Biorę tylko dalsze.
Potem odpowiednio zmniejszam dostępną pojemność, ale z głową, nie poniżej zera.
Jeśli zostały jakieś dane, to puszczam je dalej.
Cały cykl się powtarza. Przy którymś strumieniu dostępna pojemność wreszcie sięgnie 0; od tego momentu wszystko będzie przelatywało w niezmienionej postaci.

Uwaga

Od teraz wszystkie konsolowe polecenia – póki nie powiem inaczej – wykonuję w tym samym folderze, w którym jest mój skrypt.
Żeby otworzyć tam konsolę, mogę po prostu odwiedzić ten folder w domyślnym eksploratorze Minta, kliknąć prawym przyciskiem myszy pustą przestrzeń i wybrać opcję Otwórz w terminalu.

Problem pierwszy: niewykonywalność

Miałem swój skrypt, zaś w nim wlot, część przetwarzającą i wylot. Pozostało sprawdzić, co się stanie po połączeniu go rurami z konsolową klasyką:

echo 'Testowy tekst' | zbiornik | wc

A tu błąd. Informacja o braku potrzebnych pozwoleń :roll_eyes:

To dlatego, iż na Linuksie jest coś takiego jak wykonywalność plików. Nie da się tak po prostu wpinać własnych rzeczy w konsolowy „rurociąg”, odpowiednio ich wcześniej nie oznaczając.
Analogia? Mój niewykonywalny plik był jak coś oklejonego czarno-żółtymi taśmami i opatrzonego tabliczką z zakazem korzystania. Żaden szanujący się system-inspektor mi tego nie podłączy, choćbym chciał.

W przypadku Linuksa można bardzo łatwo ściągać te ograniczenia. Trzeba w tym celu uruchomić konsolę w tym samym folderze co skrypt, po czym użyć polecenia:

chmod +x zbiornik

Ta komenda włącza wykonywalność na wszystkich poziomach. Na komputerze osobistym, którego jestem panem i władcą, nie widzę w tym problemu. Ale niektórzy mogliby działać ostrożniej.

Od tej pory mój zbiornik stał się plikiem wykonywalnym. W oczach systemu przestał być tylko wsadem do maszyn i stał się czymś, co można podłączać do rurociągów wszelakich.

Problem drugi: niewskazanie Pythona

Mimo powyższej zmiany komenda przez cały czas by nie działała. Dlaczego? Bo skrypt Pythona to jedynie odrobina tekstu.

Instrukcje. Jak kartka mówiąca, iż należy zrobić na maszynie to i owo. Ale do wykonania tej instrukcji potrzeba jeszcze maszyny z prawdziwego zdarzenia. A skrypt – kartka papieru – nią nie jest. Maszyną jest sam Python (a żeby powiedzieć formalniej: interpreter Pythona).

Inne porównanie? Skrypt jest jak nabierak, ale bez koparki. Jak przyczepa bez samochodu, opryskiwacz bez traktora. I inne rzeczy w tym stylu – to moduł, który trzeba podłączyć do czegoś z silnikiem.

Żeby działało, muszę jakoś nakazać konsoli: „ten plik odczytaj Pythonem”.
Jedną z opcji jest zrobienie tego wprost. W moim przypadku nowsza wersja Pythona (3) figuruje w konsoli jako python3 i właśnie takim słowem mogę ją przywołać:

echo 'Testowy tekst' | python3 zbiornik | wc

I bingo, program zadziała!
…Tylko iż każdorazowe wołanie Pythona nieco się kłóci z prostotą, do tego polecenie by nie zadziałało, gdyby go użyć w innym folderze niż ten ze skryptem. Czas się pozbyć tych słabości.

Uwaga

Nie jest to jakąś uniwersalną zasadą, iż wersji 3 Pythona odpowiada skrót python3. Tak było u mnie (Linux Mint), a Python był zainstalowany domyślnie.
Z kolei na Termuksie trzeba wpisać polecenie instalujące (co opisuję), a potem przyzywać Pythona samym słowem python.
Na Windowsie też trzeba go pobrać i zainstalować; do tego zaznaczyć podczas instalacji opcję w stylu „Dodaj do zmiennych środowiskowych”, żeby zyskać przyzywalność (słowem bodaj python albo python.exe).

Ulepszenie: magiczna linijka

Zadbam teraz o to, żeby skrypt był domyślnie otwierany przez Pythona i żebym nie musiał go stale wołać przez python3 zbiornik. Będzie mi potrzebna pełna ścieżka do mojego Pythona. A ujawni mi ją chociażby komenda konsolowa type python3:

/usr/bin/python3

Zdobytą ścieżkę należy wstawić w „magicznej linijce” na samym początku skryptu Pythona, dopisując przed nią #!:

#!/usr/bin/python

W ten sposób skrypt został podpięty do konkretnego Pythona. Będzie automatycznie się z nim “łączył” po uruchomieniu w konsoli.

Ciekawostki

Krzyżyk na początku linijki oznacza w Pythonie komentarze. Dzięki jego obecności skrypt zostanie bezproblemowo odczytany choćby przez programy nierozumiejące magicznych linijek (ale rozumiejące Pythona).
Poza tym dość interesująca ścieżka wychodzi na Termuksie – jako „szeregowa” aplikacja nie zajmuje on żadnego uprzywilejowanego miejsca w systemie. Dlatego przed zwyczajowym usr/bin/python jego ścieżka zawiera całą drogę prowadzącą od rdzenia Androida do apki Termux: /data/data/com.termux/files/.

I dla jasności schemat świeżo dodanego powiązania skryptowo-programowego:

Ulepszenie: wzywanie z dowolnego miejsca

To co, mogę wreszcie użyć upragnionego polecenia?

echo 'Testowy tekst' | zbiornik | wc

…Nie, przez cały czas nie działa. Nie znajduje Zbiornika, choć jest w tym samym folderze. Dlaczego?

Otóż mój skrypt jest dla systemu taką płotką, nikim. System go nie zna i trzeba wprost mu mówić, gdzie ma go szukać, podając do niego ścieżkę:

  • jeśli jestem w tym samym folderze – mogę napisać ./zbiornik (gdzie ./ oznacza „patrz w aktywnym folderze”);
  • jeśli jestem w innym folderze, to muszę podać dłuższą ścieżkę do pliku ze skryptem – pełną albo względną.

A ja tych ścieżek nie chcę, chcę przywoływać jednym słowem: zbiornik. W jaki sposób mogę dać mojemu skryptowi przywileje, które na to pozwolą?

Rozpoznawalność opiera się na szczęście na prostej zasadzie – żeby dało się wołać programy po samej nazwie, muszą się znajdować w którymś ze specjalnych folderów. Ich kwestię już kiedyś poruszyłem w innym wpisie Pythonowo-konsolowym.

Żeby poznać te specjalne lokalizacje, mogę wpisać w konsolę echo $PATH. Wyświetli się lista pełnych ścieżek do folderów, rozdzielana średnikami. Skrypt można umieścić w dowolnym z nich. Na Linuksie dobrą opcją jest na przykład $HOME/.local/bin (gdzie zamiast $HOME będzie nazwa użytkownika, inna dla wszystkich).
Polecenie kopiujące Zbiornik w to miejsce:

cp zbiornik $HOME/.local/bin
Porady

Na Termuksie ścieżka będzie inna niż ta wyżej i będzie zakończona na /usr/bin. To tam należy przenosić pliki.
Gdybyśmy natomiast spróbowali przenieść plik do /usr/bin czy innej lokalizacji systemowej na Linuksie, to wyskoczyłaby informacja o braku pozwolenia. Chcąc tam kopiować pliki, trzeba dopisać na początku komendy sudo i spację, a po jej wykonaniu wpisać hasło.

Od teraz wszystko działa jak powinno – krótkie polecenie echo 'Testowy tekst' | zbiornik | wc da ten sam wynik w każdym folderze. W roli wisienki na torcie dam tu pełen schemat działania:

Podsumowanie

Czasem wystarczy kilka kroków, żeby stworzyć własny skrypt dobrze współpracujący z kultowymi klasykami Linuksa, jak wc. U mnie były to takie kroki:

  • dodanie możliwości czytania z systemu danych wejściowych i wyjściowych (sys.stdin oraz sys.stdout),
  • włączenie wykonywalności skryptu,
  • dodanie magicznej linijki wskazującej ścieżkę do Pythona,
  • umieszczenie skryptu w specjalnym, ogólnodostępnym folderze.

Efekt tego połączenia jest taki, iż zaciera się granica między tym co systemowe, a tym co moje. Mogę przywoływać zbiornik jednym słowem i go łączyć z legendami Linuksa:

echo 'Kap' | zbiornik | wc

Do wc nie trafi nic, bo pojemność Zbiornika (5) była większa niż 4-bajtowe kapnięcie (trzy litery i znak końca linijki). Zatrzymał wszystko. Ale jeżeli wpadnie coś większego, to liczarka nie będzie miała wolnego:

echo 'Testowy tekst' | zbiornik | wc

Gdybym chciał zapobiec przelaniu, nic nie stoi na przeszkodzie, żebym po prostu postawił na drodze więcej zbiorników:

echo 'KapKap' | zbiornik | zbiornik | wc

Mogę też skierować przelewające się dane do jakiegoś niefortunnego pliku :smiling_imp:

echo 'Duża ilość wody' | zbiornik >> moja_piwnica.txt

Znak > to również taka rura, tylko iż kierująca dane do pliku, a nie programu. Z kolei użycie podwójnego znaku (>>) dopisuje dane do końca pliku, zamiast całkiem go nadpisywać.

Potencjał Linuksa jest ogromny. Jak wspomniałem na początku, konsola nie jest żadną koniecznością. Ale znając parę zasad, można gwałtownie i sprawnie tworzyć własne rzeczy, integrować je ze sobą i dopasować urządzenie do własnych potrzeb i zachcianek. Zyskać poczucie wolności, o jakie czasem coraz trudniej na tym świecie :smile:

I na tym skończę główną część wpisu. Dalej będzie już parę możliwych usprawnień, które pozwoliłyby jeszcze lepiej wykorzystać potencjał konsolki (a dokładniej strumienie błędów oraz argumenty).

Swoją drogą… Mój Zbiornik to takie trochę ponowne wynalezienie koła cuta – programiku ucinającego kilka pierwszych wskazanych rzeczy.

Bonus: możliwe modyfikacje

Załóżmy, iż podczas działania Zbiornika chciałbym również wyświetlać w konsoli jakieś informacje. Na przykład ostrzec użytkowników, iż danych było sporo i się przelały.

Ale, ze względu na specyfikę programu, mam tu utrudnione zadanie. Gdybym użył typowego print('komunikat') z Pythona, to tekst zostałby dołączony do wylatujących danych i wskazania wc byłyby zawyżone.

Rozwiązaniem może tu być (nad-)użycie wyjścia na błędy. To taka osobna przegródka, poza głównym strumieniem danych. Wrzucone tu komunikaty wyświetlą się użytkownikom (może choćby w szczególnym kolorze, jeżeli tak sobie ustawili), ale nie wpłyną na główny przepływ.

Żeby kierować dane do tej przegrody, mogę dopisać do swojego kodu, tuż nad linijką z sys.stdout:

sys.stderr.write( 'Przelało się!\n' )

Znak końca linii dodaję tu wprost, bo domyślnie by go nie było.

Innym przydatnym usprawnieniem byłaby możliwość przyjmowania argumentów. Żeby dało się, przez dopisanie jednej krótkiej rzeczy, zmieniać działanie programu. I na przykład wskazywać, iż dany zbiornik ma mieć pojemność inną niż domyślna.

W tym celu warto sięgnąć do zmiennej sys.argv, która jest listą argumentów związanych z danym programem.
Jeśli użyjemy Zbiornika luzem, to ta lista będzie zawierała tylko jeden element, nazwę programu. Ale jeżeli po tej nazwie coś w konsoli dopiszemy, oddzielając to spacjami, to lista się odpowiednio rozrośnie.

Wniosek? Możemy sobie przyjąć konwencję, iż drugi argument (jeśli jest) zawsze traktujemy jak liczbę narzucającą pojemność zbiornika. I dopisujemy w kodzie, pod pierwszym określeniem empty_space, ale nad pętlą:

if len(sys.argv) == 2: empty_space = int(sys.argv[1])

Lojalnie uprzedzam: kod czysto ilustracyjny, z zerową odpornością na rzeczy nietypowe. jeżeli użytkownik wpisze w konsoli coś innego niż dodatnią liczbę, to się wszystko posypie.

Efekt? jeżeli chcemy, możemy od dzisiaj dopisywać po zbiorniku jego pojemność. I, jeżeli zajdzie taka potrzeba, postawić na drodze przepływu większy zbiornik:

echo 'KapKap' | zbiornik 10 | wc

…A gdybyśmy chcieli tworzyć bardziej złożone programy konsolowe, z własnymi podprogramami lub wbudowaną instrukcją, to Python ma w zanadrzu moduł argparse.

To tyle na dziś! Na koniec zachęcam do osobistej zabawy z przykładem i dodawania nowych bajerów. Przez zabawę najfajniej przełamać niechęć do konsoli, wiem coś o tym :wink:

Do zobaczenia w kolejnych, już bardziej aferowo-prywatnościowych wpisach! Setka już jest, to czas na marsz po 128.

Idź do oryginalnego materiału