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

Zuverlässiges Hosting für Websites mit DDoS-Schutz kaufen, VPS VDS Server 🔥 Zuverlässiges Hosting für Websites mit DDoS-Schutz kaufen, VPS VDS Server - ProHoster