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

Dobrý den všem.

V současnosti je Python jedním z nejpoužívanějších jazyků v oblasti vývoje nejen samotných softwarových produktů, ale také jejich infrastruktury. V důsledku toho se mnozí devopsáci, ať už chtěli nebo ne, museli naučit nový jazyk, který by používali jako doplněk ke starým známým Bash skriptům. Nicméně, Bash a Python zastávají různé přístupy k psaní kódu a mají určité vlastnosti, což znamená, že portování Bash skriptů do „hadího jazyka“ může být někdy časově náročná a nikoli triviální úloha.

Abychom devopsákům usnadnili život, bylo vytvořeno a stále se vytváří mnoho užitečných knihoven a utilit v Pythonu. Tento článek popisuje rovnou dvě nové knihovny, které autor tohoto příspěvku vytvořil — smart-env a python-shell — a mají za cíl zbavit devopsáka nutnosti věnovat mnoho pozornosti nuancím práce s Pythonem, což mu umožňuje soustředit se na zajímavější úkoly. Oblast působení knihoven zahrnuje proměnné prostředí a spouštění externích utilit.

Kdo se zajímá, prosím, podívejte se dál.

Nové "kola"?

Zdálo by se, proč vytvářet nové balíčky pro poměrně běžné operace? Co brání použít přímo os.environ a subprocess.<metoda nebo třída podle vaší chuti>?

Důkazy ve prospěch každé z knihoven uvedu samostatně.

Knihovna smart-env

Než začnete psát vlastní dílo, je užitečné prozkoumat internet a hledat hotová řešení. Samozřejmě, hrozí riziko, že nenajdete to, co potřebujete, ale to je spíše „pojistný případ“. Obecně platí, že tento přístup funguje a šetří spoustu času a sil.

Podle výsledků hledání bylo zjištěno následující:

  • existují balíčky, které skutečně obalují volání k os.environ, ale vyžadují spoustu rozptylujících akcí (vytvoření instance třídy, speciální parametry v voláních atd.);
  • existují slušné balíčky, které jsou však pevně vázány na určitou ekosystém (většinou na webové frameworky jako Django) a proto bez úprav vůbec nejsou univerzální;
  • existují vzácné pokusy vytvořit něco nového. Například, přidat typování a jasně parsovat hodnoty proměnných voláním metod ve formátu
    get_<typename>(var_name),

    Nebo zde další řešení, které však dnes již nepodporuje opomíjený Python 2 (na kterém, navzdory oficiálnímu R.I.P., stále zbývá hromada napsaného kódu a celé ekosystémy);

  • existují školní studentské projekty, které se dostaly do upstreamového PyPI a jen vytvářejí problémy s názvy nových balíčků (konkrétně název „smart-env“ — nucené opatření).

A tento seznam může pokračovat dlouho. Nicméně výše uvedených bodů bylo dost na to, aby mě nadchla myšlenka vytvořit něco pohodlného a univerzálního.

Požadavky kladené na psaní smart-env:

  • Maximálně jednoduchá schéma použití
  • Snadno konfigurovatelná podpora typování dat
  • Kompatibilita s Python 2.7
  • Dobré pokrytí kódu testy

Nakonec se vše podařilo realizovat. Zde je příklad použití:

from smart_env import ENV

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

# předpokládáme, že jste nastavili proměnnou MYVAR na "True"

ENV.enable_automatic_type_cast()

my_var = ENV.MY_VAR  # Rovná se boolean True

ENV.NEW_VAR = 100  # Nastaví novou proměnnou prostředí

Jak je vidět z příkladu, pro práci s novou třídou stačí ji importovat (vytvářet instanci není potřeba — mínus zbytečný krok). Přístup k jakékoli proměnné prostředí se dosahuje voláním jako k proměnné třídy ENV, což vlastně činí tuto třídu intuitivním obalem původního systémového prostředí, zatímco ji současně přetváří na možnou variantu konfiguračního objektu prakticky jakéhokoli systému (podobného přístupu je dosaženo například v Django, kde konfiguračním objektem je přímo modul/paket settings).

Zapínání/vypínání režimu podpory automatického typování se dosahuje pomocí dvou metod — enable_automatic_type_cast() a disable_automatic_type_cast(). To může být užitečné, pokud v proměnné prostředí leží serializovaný JSON-podobný objekt nebo i prostá booleovská konstanta (výslovné nastavení proměnné DEBUG v Django porovnáním s „povolenými“ řetězci — jeden z často se vyskytujících případů). Ale nyní není třeba výslovně konvertovat řetězce — většina potřebných akcí je již obsažena v hloubkách knihovny a čeká na signál k akci. 🙂 V celku funguje typování transparentně a podporuje téměř všechny běžné datové typy (nebyly testovány frozenset, complex a bytes).

Požadavek na podporu Pythonu 2 byl realizován prakticky bez obětí (vzdání se typing a některých „cukrovinek“ posledních verzí Pythonu 3), zejména díky všudypřítomnému six (pro řešení problémů s použitím metaklassů).

Ale existují i některá omezení:

  • Podpora Pythonu 3 zahrnuje verzi 3.5 a vyšší (jejich přítomnost ve vašem projektu je výsledkem buď lenosti, nebo absencí potřeby pro vylepšení, protože je těžké vymyslet objektivní důvod, proč ještě sedíte na 3.4);
  • V Pythonu 2.7 knihovna nepodporuje deserializaci literálů množin. Popis tady. Ale pokud by někdo chtěl implementovat – vítáni:);

Knihovna také vyznává mechanismus výjimek pro případ chyb parsing. Pokud nebyl řetězec rozpoznán žádným z dostupných analyzátorů, zůstává hodnota řetězcová (spíše z hlediska pohodlí a zpětné kompatibility s běžnou logikou práce proměnných v Bash).

Knihovna python-shell

Teď vám povím o druhé knihovně (popis nedostatků existujících analogů vynechám – je podobné tomu, co bylo popsáno pro smart-env. Analogy – tady a tady).

Celkově je myšlenka implementace a její požadavky analogické těm, které byly popsány pro smart-env, což je vidět z příkladu:

from python_shell import Shell

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

command = Shell.whoami()  # Rovná se "whoami"
print(command.output)  # vypíše vaše aktuální uživatelské jméno

print(command.command)  # vypíše "whoami"
print(command.return_code)  # vypíše "0"
print(command.arguments)  # vypíše ""

Shell.mkdir('-p', '\/tmp\/new_folder')  # vytvoří novou složku

Myšlenka je taková:

  1. Jedna třída, zosobňující Bash ve světě Pythonu;
  2. Každý příkaz Bash je vyvolán jako funkce třídy Shell;
  3. Parametry volání každé funkce jsou dále předávány do volání odpovídajícího příkazu Bash;
  4. Každý příkaz je vykonán „hned a teď“ v okamžiku jeho vyvolání, tj. funguje synchronní přístup;
  5. je tu možnost přístupu k výstupu příkazu ve stdout, stejně jako kódu jeho návratu;
  6. Pokud příkaz není v systému – vyhodí se výjimka.

Stejně jako v případě smart-env je zajištěna podpora Pythonu 2 (ale obětí krve bylo potřeba o něco více) a není zde podpora Pythonu 3.0-3.4.

Plány na rozvoj knihoven

Knihovny lze používat již nyní: obě jsou uloženy na oficiálním PyPI. Zdrojové kódy jsou k dispozici na Githubu (viz níže).

Obě knihovny se budou vyvíjet s ohledem na zpětnou vazbu od zájemců. A zatímco v smart-env může být obtížné vymyslet rozmanitost nových funkcí, v python-shell určitě zbývá mnoho co přidat:

  • podpora neblokujících volání;
  • možnost interaktivního komunikování s týmem (práce se stdin);
  • přidání nových vlastností (například property pro získání výstupu ze stderr);
  • realizace katalogu dostupných příkazů (pro použití s funkcí dir());
  • atd.

Odkazy

  1. Knihovna smart-env: Github a PyPI
  2. Knihovna python-shell: Github a PyPI
  3. Telegramový kanál aktualizací knihoven

UPD 23.02.2020:
* Repozitáře byly přesunuty, odpovídající odkazy byly aktualizovány
* Verze python-shell==1.0.1 se chystá na vydání 29.02.2020. Mezi změnami je podpora automatického doplňování příkazů a příkaz dir(Shell), spuštění příkazů s Pythonem-nevalidním identifikátorem, oprava chyb.

Zdroj: habr.com

Koupit spolehlivý hosting pro webové stránky s ochranou proti DDoS, VPS VDS servery 🔥 Koupit spolehlivý hosting pro webové stránky s ochranou proti DDoS, VPS VDS servery | ProHoster