Împreunăm Python și Bash: bibliotecile smart-env și python-shell

Bună ziua tuturor.

În prezent, Python este unul dintre cele mai utilizate limbaje în domeniul dezvoltării nu doar a produselor software, ci și a infrastructurii acestora. Drept urmare, mulți devops, fie din voința lor, fie împotriva acesteia, au fost nevoiți să învețe un nou limbaj pentru a-l folosi ca supliment la vechile scripturi Bash. Cu toate acestea, Bash și Python au abordări diferite în scrierea codului și au caracteristici specifice, motiv pentru care portarea scripturilor Bash pe "limbajul șerpilor" se dovedește uneori a fi o sarcină complexă și departe de a fi trivială.

Pentru a le ușura viața devops-ilor, au fost create și continuă să fie create multe biblioteci și utilitare utile pe Python. Acest articol descrie două biblioteci noi, create de autorul acestui post — smart-env și python-shell — care au scopul de a scuti devops-ul de necesitatea de a acorda multă atenție nuanțelor utilizării Python, lăsând spațiu pentru sarcini mai interesante. Domeniul de activitate al bibliotecilor este variabilele de mediu și execuția utilitare externe.

Cine este interesat, vă rog să citiți mai departe.

Biciclete noi?

Pare că nu are sens să creezi noi pachete pentru operațiuni destul de comune? Ce te împiedică să folosești direct os.environ și subprocess.?

Voi oferi dovezi în favoarea fiecărei biblioteci separat.

Biblioteca smart-env

Înainte de a-ți scrie propria creație, este util să cauți în Internet soluții deja disponibile. Desigur, există riscul de a nu găsi ceea ce ai nevoie, dar aceasta este mai degrabă o „caz de urgență”. De regulă, această abordare funcționează și economisește o mulțime de timp și efort.

Rezultatele cercetare s-au descoperit următoarele:

  • există pachete care, într-adevăr, învăluiesc apelurile la os.environ, însă necesită multe acțiuni care distrag atenția (crearea unei instanțe de clasă, parametrii speciali în apeluri etc.);
  • există pachete destul de bune, care sunt însă strâns legate de o anumită ecosistemă (în principal, de framework-uri web precum Django) și prin urmare, fără ajustări, nu sunt deloc universale;
  • există încercări rare de a face ceva nou. De exemplu, a adăuga tipizare și a parsa în mod clar valorile variabilelor prin apelul metodelor de tipul
    get_(nume_var)

    Sau încă o altă soluție , care, cu toate acestea, nu suportă acum Python 2, (pe care, în ciuda, care nu mai suportă acum versiunea de Python 2, care a căzut în desuetudine (deși, în ciuda oficial R.I.P., încă mai există munți de cod scris și întregi ecosisteme);

  • există lucrări școlare și studențești, care nu au niciun sens în PyPI-ul principal și creează doar probleme cu denumirea noilor pachete (în special, denumirea „smart-env” este o măsură forțată).

Și această listă poate continua mult timp. Totuși, cele menționate mai sus sunt suficiente pentru a aprinde ideea de a face ceva convenabil și universal.

Cerințele care au fost impuse la scrierea smart-env:

  • O schemă de utilizare maxim simplă
  • Suport pentru tipizarea datelor ușor configurabil
  • Compatibilitate cu Python 2.7
  • O acoperire bună a codului prin teste

În cele din urmă, toate acestea au fost realizate. Iată un exemplu de utilizare:

from smart_env import ENV

print(ENV.HOME)  # Echivalent cu print(os.environ['HOME'])

# presupunând că ai setat variabila de mediu MYVAR la "True"

ENV.enable_automatic_type_cast()

my_var = ENV.MY_VAR  # Echipare boolean True

ENV.NEW_VAR = 100  # Setează o nouă variabilă de mediu

După cum se poate observa din exemplu, pentru a utiliza noua clasă este suficient să o imporți (nu este necesar să creezi un exemplar — minus un pas suplimentar). Accesul la orice variabilă de mediu se face prin referire la ea ca la o variabilă a clasei ENV, ceea ce, practic, transformă această clasă într-o învăluire intuitivă a mediului sistemului nativ, transformându-l simultan într-o variantă posibilă de obiect de configurare pentru aproape orice sistem (o abordare similară, de exemplu, este folosită în Django, doar că acolo obiectul de configurare este modulul/pachetul settings).

Activarea/dezactivarea modului de suport pentru tipizarea automată se realizează prin utilizarea a două metode — enable_automatic_type_cast() și disable_automatic_type_cast(). Aceasta poate fi convenabilă dacă în variabila de mediu există un obiect similar cu JSON serializat sau chiar o constantă booleană (specificarea explicită a variabilei DEBUG în Django prin compararea variabilei de mediu cu „stringuri permise” — unul dintre cazurile frecvente întâlnite). Dar acum nu mai este nevoie să convertești explicit stringurile — cea mai mare parte a acțiunilor necesare sunt deja integrate în fundamentele bibliotecii și doar așteaptă semnalul pentru acțiune. 🙂 În general, tipizarea funcționează transparent și suportă aproape toate tipurile de date încorporate (frozenset, complex și bytes nu au fost testate).

Cerința de suport pentru Python 2 a fost implementată practic fără sacrificii (renunțând la typing și la unele „dulciuri” din ultimele versiuni de Python 3), în special datorită omniprezentului six (pentru a rezolva problemele legate de utilizarea metaclaselor).

Dar există și câteva limitări:

  • Suportul pentru Python 3 presupune versiunea 3.5 și mai sus (prezența lor în proiectul tău este rezultatul fie a lenevei, fie a lipsei unei necesități de îmbunătățiri, deoarece e greu de găsit un motiv obiectiv pentru care să mai fii pe 3.4);
  • În Python 2.7, biblioteca nu suportă deserializarea literailor seturilor. Descrierea aici. Dar, dacă cineva vrea să implementeze - bine ai venit:);

Biblioteca implementează de asemenea un mecanism de excepție în caz de erori de parsare. Dacă o linie nu poate fi recunoscută de niciunul dintre analizatorii disponibili, valoarea rămâne sub formă de șir (mai degrabă din considerente de comoditate și compatibilitate inverse cu logica obișnuită de funcționare a variabilelor în Bash).

Biblioteca python-shell

Acum voi vorbi despre a doua bibliotecă (descrierea dezavantajelor analogilor disponibili este omisă - este similară cu cea descrisă pentru smart-env. Analogii - aici și aici).

În general, ideea implementării și cerințele acesteia sunt similare celor descrise pentru smart-env, ceea ce se poate observa din exemplul:

from python_shell import Shell

Shell.ls('-l', '$HOME')  # Egal cu "ls -l $HOME"

command = Shell.whoami()  # Egal cu "whoami"
print(command.output)  # afișează numele utilizatorului curent

print(command.command)  # afișează "whoami"
print(command.return_code)  # afișează "0"
print(command.arguments)  # afișează ""

Shell.mkdir('-p', '\/tmp\/new_folder')  # creează un folder nou

Ideea este următoarea:

  1. O clasă unică, care întruchipează Bash în lumea Python;
  2. Fiecare comandă Bash este invocată ca o funcție a clasei Shell;
  3. Parametrii apelului fiecărei funcții sunt apoi transmiși apelului comenzii Bash corespunzătoare;
  4. Fiecare comandă este executată „aici și acum” în momentul invocării, adică se folosește o abordare sincronă;
  5. există posibilitatea de a accesa ieșirea comenzii în stdout, precum și codul acesteia de returnare;
  6. Dacă comanda nu există în sistem - se aruncă o excepție.

La fel ca în cazul smart-env, se asigură suport pentru Python 2 (de fapt, a fost nevoie de puțin mai multă „sânge de sacrificiu”) și nu se suportă Python 3.0-3.4.

Planuri pentru dezvoltarea bibliotecilor

Bibliotecile pot fi folosite deja: ambele sunt disponibile pe PyPI oficial. Sursa este accesibilă pe Github (vezi mai jos).

Ambele biblioteci se vor dezvolta ținând cont de feedback-ul adunat de la cei interesați. Și, deși în smart-env poate fi greu să găsești diversitate în noi caracteristici, în python-shell cu siguranță mai avem de adăugat:

  • suport pentru apeluri non-blocante;
  • posibilitatea de interacțiune directă cu echipa (lucrând cu stdin);
  • adăugarea de noi proprietăți (de exemplu, proprietatea pentru a obține ieșirea din stderr);
  • implementarea unui catalog al comenzilor disponibile (pentru utilizarea cu funcția dir());
  • etc.

Linkuri

  1. Biblioteca smart-env: Github și PyPI
  2. Biblioteca python-shell: Github și PyPI
  3. Canalul Telegram actualizărilor bibliotecilor

UPD 23.02.2020:
* Repositoarele au fost mutate, link-urile corespunzătoare au fost actualizate
* Versiunea python-shell==1.0.1 este pregătită pentru lansare pe 29.02.2020. Printre modificări se numără suportul pentru completarea automată a comenzilor și comanda dir(Shell), execuția comenzilor cu un identificator invalid în Python, corectarea bug-urilor.

Sursa: habr.com

Cumpără un hosting fiabil pentru site-uri cu protecție DDoS, servere VPS VDS 🔥 Cumpără un hosting fiabil pentru site-uri cu protecție DDoS, servere VPS VDS | ProHoster