Kombinieren von Python und Bash: die Bibliotheken smart-env und python-shell

Guten Tag allerseits.

Heutzutage ist Python eine der am hĂ€ufigsten verwendeten Sprachen fĂŒr die Erstellung von nicht nur Softwareprodukten, sondern auch fĂŒr den Aufbau ihrer Infrastruktur. Infolgedessen mussten viele DevOps, ob sie wollten oder nicht, eine neue Sprache lernen, um sie als ErgĂ€nzung zu den altbewĂ€hrten Bash-Skripten zu verwenden. Bash und Python verfolgen jedoch unterschiedliche AnsĂ€tze beim Schreiben von Code und weisen bestimmte Besonderheiten auf, weshalb die Portierung von Bash-Skripten auf die „Schlangensprache“ manchmal eine anspruchsvolle und alles andere als triviale Aufgabe darstellt.

Um das Leben der DevOps zu erleichtern, wurden viele nĂŒtzliche Bibliotheken und Tools in Python geschaffen und weiterhin entwickelt. Dieser Artikel beschreibt gleich zwei neue Bibliotheken, die der Autor dieses Beitrags erstellt hat - smart-env und python-shell - die dazu dienen, den DevOps die Notwendigkeit zu nehmen, viel Zeit mit den Feinheiten der Python-Arbeit zu verbringen, und Platz fĂŒr interessantere Aufgaben zu lassen. Der TĂ€tigkeitsbereich dieser Bibliotheken umfasst Umgebungsvariablen und das Starten externer Tools.

Wer interessiert ist, ist herzlich eingeladen, weiterzulesen.

Neue "FahrrÀder"?

Es wĂŒrde scheinen, warum neue Pakete fĂŒr ziemlich gewöhnliche Operationen erstellen? Was hindert daran, directly os.environ und subprocess. zu verwenden?

Die Beweise fĂŒr jede der Bibliotheken werde ich separat anfĂŒhren.

Die Bibliothek smart-env

Bevor ich mein eigenes Werk schreibe, ist es hilfreich, im Internet nach bestehenden Lösungen zu suchen. NatĂŒrlich besteht das Risiko, nicht das GewĂŒnschte zu finden, aber das ist eher ein "Versicherungsfall". In der Regel funktioniert der Ansatz jedoch und spart eine Menge Zeit und MĂŒhe.

Laut den Ergebnissen Bei der Suche wurde Folgendes festgestellt:

  • Es gibt Pakete, die tatsĂ€chlich Aufrufe zu os.environ kapseln, aber gleichzeitig eine Menge ablenkender Aktionen erfordern (Klassenerstellung, spezielle Parameter in Aufrufen usw.);
  • Es gibt nicht schlechte Pakete, die jedoch stark an ein bestimmtes Ökosystem gebunden sind (hauptsĂ€chlich an Web-Frameworks wie Django) und daher ohne Nachbearbeitung ĂŒberhaupt nicht universell sind;
  • Es gibt seltene Versuche, etwas Neues zu schaffen. Zum Beispiel Typisierung hinzuzufĂŒgen und die Werte der Variablen explizit durch Aufrufe von Methoden wie
    get_(var_name) zu parsen.

    Oder hier ist eine weitere Lösung, die jedoch den mittlerweile veralteten Python 2 nicht unterstĂŒtzt (auf dem, trotz ... offizielles R.I.P., es bleiben immer noch Berge von geschriebenem Code und ganze Ökosysteme);

  • Es gibt schulische und studentische Bastelprojekte, die ĂŒberhaupt nicht klar sind, warum sie im Upstream PyPI gelandet sind und nur Probleme bei der Benennung neuer Pakete verursachen (insbesondere der Name „smart-env“ ist eine Notlösung).

Und diese Liste könnte lange fortgesetzt werden. Die oben genannten Punkte waren jedoch ausreichend, um die Idee zu entfachen, etwas Praktisches und Universelles zu schaffen.

Anforderungen, die an die Erstellung von smart-env gestellt wurden:

  • Maximal einfache Nutzungsschema
  • Einfach konfigurierbare UnterstĂŒtzung fĂŒr Datentypisierung
  • KompatibilitĂ€t mit Python 2.7
  • Gute Testabdeckung des Codes

Letztendlich ist es gelungen, all dies umzusetzen. Hier ist ein Beispiel fĂŒr die Nutzung:

from smart_env import ENV

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

# vorausgesetzt, Sie haben die Umgebungsvariable MYVAR auf "True" gesetzt

ENV.enable_automatic_type_cast()

my_var = ENV.MY_VAR  # Entspricht boolean True

ENV.NEW_VAR = 100  # Setzt eine neue Umgebungsvariable

Wie aus dem Beispiel ersichtlich, ist es genug, die neue Klasse zu importieren (es ist nicht nötig, eine Instanz zu erstellen – das spart unnötige Schritte). Der Zugriff auf jede Umgebungsvariable erfolgt, indem auf sie als Klassenvariable ENV zugegriffen wird, was diesen Klasse tatsĂ€chlich zu einer intuitiv verstĂ€ndlichen HĂŒlle fĂŒr die native Systemumgebung macht und sie gleichzeitig in eine mögliche Variante eines Konfigurationsobjekts fĂŒr praktisch jedes System verwandelt (ein Ă€hnlicher Ansatz wird beispielsweise in Django verwendet, wo das Konfigurationsobjekt das Modul/Paket settings ist).

Das Aktivieren/Deaktivieren des Modus fĂŒr automatische Typisierung erfolgt durch die Verwendung von zwei Methoden – enable_automatic_type_cast() und disable_automatic_type_cast(). Dies kann praktisch sein, wenn in der Umgebungsvariable ein serialisiertes JSON-Ă€hnliches Objekt oder sogar einfach eine boolesche Konstante gespeichert ist (die explizite Definition der Variable DEBUG in Django durch den Vergleich der Umgebungsvariable mit „erlaubten“ Strings ist einer der hĂ€ufigsten FĂ€lle). Aber jetzt ist es nicht mehr notwendig, Strings explizit zu konvertieren – die meisten erforderlichen Aktionen sind bereits im Inneren der Bibliothek und warten nur auf ein Signal zum Handeln. 🙂 Im Großen und Ganzen funktioniert die Typisierung transparent und unterstĂŒtzt fast alle vorhandenen eingebauten Datentypen (frozenset, complex und bytes wurden nicht getestet).

Die UnterstĂŒtzung fĂŒr Python 2 wurde praktisch ohne Opfer umgesetzt (Verzicht auf Typisierung und einige "SĂŒĂŸigkeiten" der letzten Versionen von Python 3), insbesondere dank des allgegenwĂ€rtigen six (zur Lösung von Problemen mit der Verwendung von Metaklassen).

Es gibt jedoch auch einige EinschrÀnkungen:

  • Die UnterstĂŒtzung fĂŒr Python 3 setzt Version 3.5 oder höher voraus (deren Vorhandensein in Ihrem Projekt ist entweder das Ergebnis von Faulheit oder des Fehlens der Notwendigkeit fĂŒr Verbesserungen, da es schwer zu finden ist, einen objektiven Grund zu nennen, warum Sie immer noch auf 3.4 sind);
  • In Python 2.7 unterstĂŒtzt die Bibliothek keine Deserialisierung von Mengenliteralen. Beschreibung hier. Aber wenn jemand es umsetzen möchte – willkommen:);

Die Bibliothek hat auch einen Ausnahmebehandlungsmechanismus fĂŒr den Fall von Parsing-Fehlern. Wenn eine Zeichenkette von keinem der verfĂŒgbaren Parser erkannt werden kann, bleibt der Wert als Zeichenkette (eher aus GrĂŒnden der Bequemlichkeit und rĂŒckwĂ€rtskompatibel zur gewohnten Logik der Variablenverwendung in Bash).

Die Bibliothek python-shell

Jetzt erzĂ€hle ich von der zweiten Bibliothek (die Beschreibung der MĂ€ngel der vorhandenen Analoga lasse ich weg – sie Ă€hnelt der fĂŒr smart-env beschriebenen. Analoga – hier und hier).

Insgesamt sind die Idee der Umsetzung und die Anforderungen daran Ă€hnlich wie die fĂŒr smart-env beschriebenen, was aus dem Beispiel ersichtlich ist:

from python_shell import Shell

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

command = Shell.whoami()  # Entspricht "whoami"
print(command.output)  # gibt Ihren aktuellen Benutzernamen aus

print(command.command)  # gibt "whoami" aus
print(command.return_code)  # gibt "0" aus
print(command.arguments)  # gibt "" aus

Shell.mkdir('-p', 'tmp/new_folder')  # erstellt einen neuen Ordner

Die Idee ist folgende:

  1. Eine einheitliche Klasse, die Bash in der Welt von Python verkörpert;
  2. Jeder Bash-Befehl wird als Funktion der Klasse Shell aufgerufen;
  3. Die Parameter des Aufrufs jeder Funktion werden dann an den entsprechenden Bash-Befehl weitergegeben;
  4. Jeder Befehl wird "hier und jetzt" zum Zeitpunkt seines Aufrufs ausgefĂŒhrt, d.h. es wird ein synchroner Ansatz verwendet;
  5. Es besteht die Möglichkeit, auf die Ausgabe des Befehls in stdout sowie auf den RĂŒckgabecode zuzugreifen;
  6. Wenn der Befehl im System nicht vorhanden ist, wird eine Ausnahme ausgelöst.

Wie im Fall von smart-env ist die UnterstĂŒtzung fĂŒr Python 2 gewĂ€hrleistet (allerdings war etwas mehr Opferblut nötig) und es gibt keine UnterstĂŒtzung fĂŒr Python 3.0-3.4.

EntwicklungsplĂ€ne fĂŒr die Bibliotheken

Die Bibliotheken können bereits jetzt verwendet werden: beide sind auf dem offiziellen PyPI veröffentlicht. Der Quellcode ist auf Github verfĂŒgbar (siehe unten).

Beide Bibliotheken werden unter BerĂŒcksichtigung des gesammelten Feedbacks von Interessierten weiterentwickelt. Und wĂ€hrend es in smart-env vielleicht schwierig ist, verschiedene neue Funktionen zu finden, gibt es in python-shell definitiv noch einiges hinzuzufĂŒgen:

  • UnterstĂŒtzung von nicht-blockierenden Aufrufen;
  • Möglichkeit der interaktiven Kommunikation mit dem Team (Arbeit mit stdin);
  • HinzufĂŒgen neuer Eigenschaften (zum Beispiel property zur Erfassung der Ausgabe von stderr);
  • Implementierung eines Verzeichnisses verfĂŒgbarer Befehle (fĂŒr die Verwendung mit der Funktion dir());
  • usw.

Links

  1. Bibliothek smart-env: Github und PyPI
  2. Bibliothek python-shell: Github und PyPI
  3. Telegram-Kanal Updates der Bibliotheken

UPD 23.02.2020:
* Repositories wurden verschoben, entsprechende Links aktualisiert
* Die Version python-shell==1.0.1 wird am 29.02.2020 veröffentlicht. Zu den Änderungen gehören die UnterstĂŒtzung von AutovervollstĂ€ndigung fĂŒr Befehle und dir(Shell), das AusfĂŒhren von Befehlen mit einem ungĂŒltigen Python-Identifikator sowie das Beheben von Fehlern.

Quelle: habr.com

60GB SSD 8Gb DDR4