Spojujeme Python a Bash: knihovny smart-env a python-shell

Dobrý deň všetkým.

V súčasnosti je Python jedným z najpoužívanejších jazykov v oblasti vytvárania nielen samotných softvérových produktov, ale aj zabezpečenia ich infraštruktúry. V dôsledku toho sa mnohým devopsovým odborníkom, či už proti svojej vôli alebo z vlastnej iniciatívy, muselo naučiť nový jazyk s cieľom doplniť svoje staré dobré Bash skripty. Avšak Bash a Python vyznávajú rôzne prístupy k písaniu kódu a majú určité špecifiká, takže portovanie Bash skriptov na „hadí jazyk“ niekedy predstavuje zložitú a rozhodne nie triviálnu úlohu.

Aby sa devopsovým odborníkom uľahčil život, bolo vytvorených a naďalej sa vytvára množstvo užitočných knižníc a utilít na Pythone. Tento článok popisuje dve nové knižnice, ktoré autor tohto príspevku vytvoril — smart-env a python-shell — a majú za cieľ zbaviť devopsových odborníkov potreby venovať veľa pozornosti nuansám práce s Python, pričom ponechávajú priestor na zaujímavejšie úlohy. Oblasť činnosti knižníc sa týka premenných prostredia a spúšťania externých utilít.

Tí, ktorých to zaujalo, prosím, pokračujte pod článkom.

Nové "bicykle"?

Zdalo by sa, prečo vytvárať nové balíky pre dosť bežné operácie? Čo bráni priamemu používaniu os.environ a subprocess.?

Dôkazy v prospech každej z knižníc uvediem osobitne.

Knižnica smart-env

Predtým, než napíšete vlastný výtvor, je dobré prehľadať Internet a hľadať hotové riešenia. Samozrejme, existuje riziko, že nenájdete to, čo potrebujete, ale to je skôr "poistná udalosť". Zvyčajne to funguje a šetrí množstvo času a síl.

Na základe hľadania bolo zistené nasledovné:

  • existujú balíky, ktoré skutočne encapsulujú volania na os.environ, avšak vyžadujú množstvo rušivých akcií (vytvorenie inštancie triedy, špeciálne parametre vo volaniach atď.);
  • existujú slušné balíky, ktoré sú však pevne previazané na určitý ekosystém (predovšetkým na webové rámce ako Django) a preto sú bez úprav úplne neuniverzálne;
  • existujú ojedinelé pokusy vytvoriť niečo nové. Napríklad pridať typovanie a jasne parsovať hodnoty premenných pomocou volania metód typu
    get_(var_name)

    Alebo tu je ešte jedno riešenie, ktoré však už nepodporuje aktuálne opustený Python 2 (na ktorom, napriek oficiálnemu R.I.P., stále zostáva množstvo napísaného kódu a celé ekosystémy);

  • existujú školskostudentské projekty, úplne nezrozumiteľne sa dostávajúce do upstream PyPI a len vytvárajúce problémy s názvami nových balíkov (najmä názov „smart-env“ — nútené opatrenie).

A tento zoznam by sa dal dlhodobo predlžovať. Avšak aj na vyššie uvedených bodoch stačilo na to, aby sa zrodila myšlienka vytvoriť niečo pohodlné a univerzálne.

Požiadavky, ktoré boli stanovené pri písaní smart-env:

  • Maximálne jednoduché schémy použitia
  • Ľahko konfigurovateľná podpora typizácie dát
  • Kompatibilita s Python 2.7
  • Dobré pokrytie kódu testami

Nakoniec sa to všetko podarilo realizovať. Tu je príklad použitia:

from smart_env import ENV

print(ENV.HOME)  # Rovná sa print(os.environ['HOME'])

# predpokladajme, že ste nastavili env premennú MYVAR na "True"

ENV.enable_automatic_type_cast()

my_var = ENV.MY_VAR  # Rovná sa boolean True

ENV.NEW_VAR = 100  # Nastaví novú premennú prostredia

Ako je vidieť z príkladu, pre prácu s novou triedou stačí ju importovať (zbytočné akcie s vytváraním inštancií nie sú potrebné). Prístup k akejkoľvek premennej prostredia sa dosahuje odkazovaním na ňu ako na premennú triedy ENV, čo v podstate robí túto triedu intuitívne pochopiteľným obalom nativného systémového prostredia, pričom ju zároveň mení na možný variant konfiguračného objektu prakticky akejkoľvek sústavy (podobný prístup sa dá dosiahnuť napríklad v Django, len tam je konfiguračným objektom priamo modul/paket settings).

Zapínanie/vypínanie režimu podpory automatickej typizácie sa dosahuje použitím dvoch metód — enable_automatic_type_cast() a disable_automatic_type_cast(). To môže byť užitočné, ak v premennej prostredia leží serializovaný JSON-podobný objekt alebo dokonca len booleovská konštanta (explicitné nastavovanie premennej DEBUG v Django prostredníctvom porovnania premennej prostredia s „prijateľnými“ reťazcami — jeden z často sa vyskytujúcich prípadov). Ale teraz už nie je potrebné explicitne konvertovať reťazce — väčšina potrebných akcií je už zakotvená v hlbinách knižnice a len čaká na signál k akcii. 🙂 V celku typizácia funguje priehľadne a podporuje takmer všetky existujúce zabudované typy dát (neboli testované frozenset, complex a bytes).

Podpora pre Python 2 bola implementovaná prakticky bez obetí (zrieknutie sa typing a niektorých "cukríkov" posledných verzií Python 3), predovšetkým vďaka všadeprítomnému six (na riešenie problémov s používaním metaclassov).

Existujú však aj určité obmedzenia:

  • Podpora Python 3 zahŕňa verziu 3.5 a novšie (ich prítomnosť vo vašom projekte je výsledkom buď lenivosti, alebo absencie potreby na vylepšenia, ťažko si predstaviť objektívny dôvod, prečo by ste ešte stále používali 3.4);
  • V Python 2.7 knižnica nepodporuje deserializáciu literálov množín. Opis tu. Ale ak by sa niekto rozhodol realizovať to — vitajte:);

Knižnica tiež zavádza mechanizmus výnimiek pre prípad chýb pri parsovaní. Ak sa reťazec nepodarí rozoznať žiadnym z dostupných analyzátorov, hodnota zostáva reťazcová (skôr z dôvodov pohodlia a spätnej kompatibility so zvyčajnou logikou práce s premennými v Bash).

Knižnica python-shell

Teraz budem hovoriť o druhej knižnici (opis nedostatkov existujúcich alternatív vynechám — je podobný tomu, čo je opísané pre smart-env. Alternatívy — tu a tu).

Celkovo je myšlienka implementácie a požiadavky na ňu podobné tým, ktoré sú opísané pre smart-env, čo je vidieť z príkladu:

from python_shell import Shell

Shell.ls('-l', '$HOME')  # Rovná sa "ls -l $HOME"

command = Shell.whoami()  # Rovná sa "whoami"
print(command.output)  # vytlačí vaše aktuálne meno používateľa

print(command.command)  # vytlačí "whoami"
print(command.return_code)  # vytlačí "0"
print(command.arguments)  # vytlačí ""

Shell.mkdir('-p', '\/tmp\/new_folder')  # vytvorí novú složku

Myšlienka je nasledujúca:

  1. Jedna trieda, ktorá zosobňuje Bash vo svete Pythonu;
  2. Každý Bash príkaz sa volá ako funkcia triedy Shell;
  3. Parametre volania každej funkcie sa ďalej prenášajú do volania príslušného Bash príkazu;
  4. Každý príkaz sa vykonáva "tu a teraz" v momente jeho vyvolania, t.j. funguje synchronný prístup;
  5. existuje možnosť získať prístup k výstupu príkazu v stdout, ako aj kódu jeho návratu;
  6. Ak príkaz nie je v systéme — vyhodí sa výnimka.

Rovnako ako v prípade smart-env, je zabezpečená podpora Python 2 (pravda, obetovaných krvi bolo o niečo viac) a nepodporuje sa Python 3.0-3.4.

Plány na rozvoj knižníc

Knižnice je možné používať už teraz: obe sú zverejnené na oficiálnom PyPI. Zdrojové kódy sú dostupné na Github (pozri nižšie).

Obe knižnice sa budú rozvíjať s ohľadom na spätnú väzbu zozbieranú od zainteresovaných osôb. A ak v smart-env môže byť ťažké vymyslieť rôzne nové funkcie, v python-shell je určite ešte čo pridať:

  • podpora neblokujúcich volaní;
  • možnosť interaktívneho komunikovania s tímom (práca s stdin);
  • pridanie nových vlastností (napríklad property na získanie výstupu zo stderr);
  • realizácia katalógu dostupných príkazov (na použitie s funkciou dir());
  • a pod.

Odkazy

  1. Knižnica smart-env: Github a PyPI
  2. Knižnica python-shell: Github a PyPI
  3. Telegramový kanál aktualizácií knižníc

UPD 23.02.2020:
* Repozitáre boli presunuté, príslušné odkazy aktualizované
* Verzia python-shell==1.0.1 sa pripravuje na vydanie 29.02.2020. Medzi zmenami je podpora automatického doplňovania príkazov a príkazu dir(Shell), spúšťanie príkazov s Python-neplatným identifikátorom, oprava chýb.

Zdroj: habr.com

Kúpte si spoľahlivý hosting pre webové stránky s ochranou proti DDoS, VPS VDS servery 🔥 Kúpte si spoľahlivý hosting pre webové stránky s ochranou proti DDoS, VPS VDS servery | ProHoster