Colleghiamo Python e Bash: le librerie smart-env e python-shell

Buonasera a tutti.

Oggi Python è uno dei linguaggi più utilizzati nel campo dello sviluppo di prodotti software e nell'infrastruttura che li supporta. A causa di ciò, molti DevOps, per scelta o necessità, hanno dovuto imparare un nuovo linguaggio da utilizzare insieme ai vecchi buoni script Bash. Tuttavia, Bash e Python seguono approcci diversi nella scrittura del codice e presentano caratteristiche specifiche, il che rende il porting degli script Bash nel 'linguaggio dei serpenti' un compito a volte complesso e tutt'altro che banale.

Per semplificare la vita ai DevOps, sono state create e continuano a essere sviluppate molte librerie e utilità utili in Python. Questo articolo descrive due nuove librerie, create dall'autore di questo post — smart-env e python-shell — pensate per liberare i DevOps dalla necessità di concentrarsi sui dettagli del funzionamento di Python, lasciando spazio per compiti più interessanti. Le librerie si occupano di variabili ambientali e dell'esecuzione di utilità esterne.

Chi fosse interessato, è pregato di approfondire.

Nuovi "bici"?

A prima vista, perché creare nuovi pacchetti per operazioni piuttosto ordinarie? Cosa impedisce di utilizzare direttamente os.environ e subprocess.?

Fornirò prove a favore di ciascuna delle librerie separatamente.

Libreria smart-env

Prima di scrivere la tua creazione, è utile navigare in Internet e cercare soluzioni già pronte. Certo, c'è il rischio di non trovare ciò di cui hai bisogno, ma questo è più un "caso assicurativo". Di solito, l'approccio funziona e fa risparmiare un sacco di tempo e fatica.

In base ai risultati della ricerca è emerso quanto segue:

  • ci sono pacchetti che effettivamente avvolgono le chiamate a os.environ, ma richiedono comunque molte azioni distraenti (creazione di un'istanza della classe, parametri speciali nelle chiamate, ecc.);
  • ci sono pacchetti che non sono affatto male, ma sono rigidamente legati a un determinato ecosistema (principalmente a framework web come Django) e quindi sono del tutto non universali senza modifiche;
  • ci sono rare tentativi di creare qualcosa di nuovo. Ad esempio, aggiungere la tipizzazione e analizzare esplicitamente i valori delle variabili chiamando metodi di tipo
    get_(var_name)

    O anche un'altra soluzione, che, però, non supporta l'attuale Python 2 (su cui, nonostante l'ufficiale R.I.P., rimangono ancora montagne di codice scritto e interi ecosistemi);

  • ci sono prodotti scolastici e universitari, del tutto incomprensibili, che si sono trovati nell'upstream di PyPI e creano solo problemi con la denominazione di nuovi pacchetti (in particolare, il nome «smart-env» è una misura forzata).

E questo elenco potrebbe continuare a lungo. Tuttavia, anche i punti sopra sono stati sufficienti per accendere l'idea di creare qualcosa di comodo e universale.

Requisiti posti per la scrittura di smart-env:

  • Schema d'uso il più semplice possibile
  • Supporto per la tipizzazione dei dati facilmente configurabile
  • Compatibilità con Python 2.7
  • Buona copertura del codice con test

Alla fine, tutto questo è stato realizzato. Ecco un esempio d'uso:

from smart_env import ENV

print(ENV.HOME)  # Equivale a print(os.environ['HOME'])

# supponendo che tu abbia impostato la variabile d'ambiente MYVAR su "True"

ENV.enable_automatic_type_cast()

my_var = ENV.MY_VAR  # Equivale a boolean True

ENV.NEW_VAR = 100  # Imposta una nuova variabile d'ambiente

Come si vede dall'esempio, per lavorare con la nuova classe è sufficiente importarla (non è necessario creare un'istanza — si elimina un'azione superflua). L'accesso a qualsiasi variabile d'ambiente avviene tramite il suo utilizzo come variabile della classe ENV, il che rende questa classe un'intuitiva astrazione dell'ambiente di sistema nativo, trasformandola parallelamente in una potenziale opzione per un oggetto di configurazione di praticamente qualsiasi sistema (un approccio simile, ad esempio, si ottiene in Django, dove l'oggetto di configurazione è direttamente il modulo/pacchetto settings).

L'attivazione/disattivazione della modalità di supporto per il casting automatico dei tipi avviene tramite l'uso di due metodi: enable_automatic_type_cast() e disable_automatic_type_cast(). Questo può risultare utile se nella variabile d'ambiente si trova un oggetto simile a JSON serializzato o persino semplicemente una costante booleana (la definizione esplicita della variabile DEBUG in Django confrontando la variabile d'ambiente con le "stringhe valide" è uno dei casi più comuni). Ma ora non è più necessario convertire esplicitamente le stringhe: gran parte delle azioni necessarie è già integrata nella libreria e aspetta solo di essere attivata. 🙂 In generale, la tipizzazione funziona in modo trasparente e supporta quasi tutti i tipi di dati incorporati esistenti (non sono stati testati frozenset, complex e bytes).

La richiesta di supporto per Python 2 è stata realizzata praticamente senza sacrifici (rinunciando a typing e ad alcune "caramelle" delle ultime versioni di Python 3), in particolare grazie all'onnipresente six (per risolvere i problemi legati all'uso dei metaclass).

Tuttavia, ci sono alcune limitazioni:

  • Il supporto per Python 3 implica la versione 3.5 o superiore (la sua presenza nel tuo progetto è il risultato di pigrizia o della mancanza di necessità di miglioramenti, poiché è difficile trovare una ragione oggettiva per continuare a utilizzare 3.4);
  • In Python 2.7, la libreria non supporta la deserializzazione dei letterali dell'insieme. Descrizione qui. Ma se qualcuno desidera implementarlo — è benvenuto:);

La libreria presenta anche un meccanismo di eccezioni per gestire gli errori di parsing. Se una stringa non può essere riconosciuta da nessuno degli analizzatori disponibili, il valore rimane una stringa (piuttosto per comodità e per mantenere la retrocompatibilità con la logica di funzionamento delle variabili in Bash).

La libreria python-shell

Ora parlerò della seconda libreria (ometto la descrizione dei difetti delle alternative esistenti — è simile a quella descritta per smart-env. Le alternative — qui e qui).

In generale, l'idea di implementazione e i requisiti sono simili a quelli descritti per smart-env, come si vede nell'esempio:

from python_shell import Shell

Shell.ls('-l', '$HOME')  # Equivale a "ls -l $HOME"

command = Shell.whoami()  # Equivale a "whoami"
print(command.output)  # stampa il tuo nome utente corrente

print(command.command)  # stampa "whoami"
print(command.return_code)  # stampa "0"
print(command.arguments)  # stampa ""

Shell.mkdir('-p', '/tmp/new_folder')  # crea una nuova cartella

L'idea è la seguente:

  1. Una classe unica che incarna Bash nel mondo di Python;
  2. Ogni comando Bash è chiamato come funzione della classe Shell;
  3. I parametri di chiamata di ogni funzione vengono poi passati alla corrispondente comando Bash;
  4. Ogni comando viene eseguito «qui e ora» nel momento in cui viene chiamato, ossia segue un approccio sincrono;
  5. è possibile accedere all'output del comando in stdout, così come al codice di ritorno;
  6. Se il comando non è presente nel sistema, viene sollevata un'eccezione.

Come nel caso di smart-env, è assicurato il supporto per Python 2 (sebbene sia servito un po' più di sangue sacrificato) e non è fornito supporto per Python 3.0-3.4.

Piani per lo sviluppo delle librerie

Le librerie possono già essere utilizzate: entrambe sono disponibili sul PyPI ufficiale. I sorgenti sono disponibili su Github (vedi sotto).

Entrambe le librerie si svilupperanno tenendo conto del feedback raccolto da chi è interessato. E, se in smart-env potrebbe essere difficile pensare a una varietà di nuove funzionalità, in python-shell c'è sicuramente ancora molto da aggiungere:

  • supporto per chiamate non bloccanti;
  • possibilità di comunicazione interattiva con il comando (lavorare con stdin);
  • aggiunta di nuove proprietà (ad esempio, una proprietà per ottenere l'output da stderr);
  • implementazione del catalogo dei comandi disponibili (per l'uso con la funzione dir());
  • ecc.

Link

  1. Libreria smart-env: Github e PyPI
  2. Libreria python-shell: Github e PyPI
  3. Canale Telegram aggiornamenti delle librerie

UPD 23.02.2020:
* I repository sono stati trasferiti, i relativi link aggiornati
* La versione python-shell==1.0.1 è prevista per il 29.02.2020. Tra le novità — supporto per l'autocomplete dei comandi e il comando dir(Shell), esecuzione di comandi con un identificatore non valido per Python, correzioni di bug.

Fonte: habr.com

Acquista hosting affidabile per siti web con protezione DDoS, VPS VDS server 🔥 Acquista hosting affidabile per siti web con protezione DDoS, VPS VDS server | ProHoster