Guten Tag allerseits.
Heutzutage ist Python eine der am häufigsten verwendeten Programmiersprachen, nicht nur zur Erstellung von Softwareprodukten, sondern auch zur Bereitstellung der Infrastruktur dafür. Deshalb mussten viele DevOps, ob sie wollten oder nicht, eine neue Sprache erlernen, um sie als Ergänzung zu den altbewährten Bash-Skripten zu nutzen. Bash und Python haben jedoch unterschiedliche Ansätze zum Codieren und bestimmte Besonderheiten, weshalb die Portierung von Bash-Skripten auf die "Schlangensprache" manchmal eine umfangreiche und keinesfalls triviale Aufgabe darstellt.
Um DevOps das Leben zu erleichtern, wurden und werden viele nützliche Bibliotheken und Tools in Python entwickelt. Dieser Artikel beschreibt gleich zwei neue Bibliotheken, die vom Autor dieses Beitrags erstellt wurden — und — und die dazu dienen, DevOps von der Notwendigkeit zu befreien, viel Aufmerksamkeit den Feinheiten der Python-Arbeit zu widmen, und stattdessen Platz für interessantere Aufgaben zu schaffen. Der Anwendungsbereich der Bibliotheken sind Umgebungsvariablen und das Starten externer Tools.
Wer Interesse hat, bitte weiterlesen.
Neue "Fahrräder"?
Es stellt sich die Frage, warum man neue Pakete für recht alltägliche Operationen erstellen sollte. Was hindert daran, direkt os.environ und subprocess. zu verwenden?
Die Beweise für jede der Bibliotheken werde ich separat aufführen.
Die Bibliothek smart-env.
Bevor man sein eigenes Werk schreibt, ist es nützlich, das Internet zu durchforsten und nach bestehenden Lösungen zu suchen. Natürlich besteht das Risiko, dass man nicht findet, was man braucht, aber das ist eher ein "Versicherungsfall". In der Regel funktioniert der Ansatz und spart eine Menge Zeit und Mühe.
Laut den Ergebnissen Folgendes wurde festgestellt:
- Es gibt Pakete, die tatsächlich die Aufrufe an os.environ kapseln, dabei jedoch eine Menge ablenkender Aktionen erfordern (Erstellung einer Klasseninstanz, spezielle Parameter in Aufrufen usw.);
- Es gibt anständige Pakete, die jedoch stark an ein bestimmtes Ökosystem (hauptsächlich an Web-Frameworks wie Django) gebunden sind und deshalb ohne Nachbearbeitung nicht wirklich universell sind;
- Es gibt seltene Versuche, etwas Neues zu schaffen. Zum Beispiel, und die Werte von Variablen durch Methodenaufrufe wie
get_(var_name)Oder hier ist , die jedoch derzeit das heutzutage nicht mehr beliebte Python 2 nicht unterstützt (auf dem, trotz der , es bleibt immer noch eine Menge geschriebenen Codes und ganze Ökosysteme);
- es gibt Schul- und Studentenprojekte, 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“ — eine erzwungene Maßnahme).
Und diese Liste könnte lange fortgesetzt werden. Aber die oben genannten Punkte reichen aus, um die Idee zu entfachen, etwas Bequemes und Universelles zu schaffen.
Die Anforderungen, die beim Schreiben von smart-env gestellt wurden:
- Maximal einfaches Nutzungsschema
- Einfach konfigurierbare Unterstützung der 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 Verwendung:
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 im Beispiel zu sehen ist, reicht es aus, die neue Klasse zu importieren (eine Instanz muss nicht erstellt werden — das spart unnötige Aktionen). Der Zugang zu jeder Umgebungsvariable erfolgt durch den Zugriff auf sie als Klasseneigenschaft ENV, was diesen Klasse im Grunde zu einer intuitiv verständlichen Wrapper des nativen Systemumfelds macht und es gleichzeitig zu einer möglichen Konfigurationsobjekt-Option für so gut wie jedes System erhebt (ein ähnlicher Ansatz wird beispielsweise in Django verfolgt, wo das Konfigurationsobjekt das Modul/Paket settings ist).
Die Aktivierung/Deaktivierung des automatischen Typumwandlungsmodus erfolgt durch die Verwendung von zwei Methoden – enable_automatic_type_cast() und disable_automatic_type_cast(). Dies kann nützlich sein, wenn in der Umgebungsvariablen ein serialisiertes JSON-ähnliches Objekt oder sogar einfach eine boolesche Konstante liegt (eine häufige Praxis ist die explizite Definition der DEBUG-Variablen in Django durch den Vergleich der Umgebungsvariablen mit "gültigen" Zeichenfolgen). Aber nun ist es nicht mehr notwendig, Zeichenfolgen explizit zu konvertieren – die meisten erforderlichen Aktionen sind bereits in die Bibliothek integriert und warten nur auf das Signal zum Handeln. 🙂 Insgesamt funktioniert die Typisierung transparent und unterstützt fast alle gängigen eingebauten Datentypen (frozenset, complex und bytes wurden nicht getestet).
Die Anforderung zur Unterstützung von Python 2 wurde nahezu ohne Opfer umgesetzt (Verzicht auf typing und einige „Zuckerpillen“ der letzten Python-3-Versionen), insbesondere dank des allgegenwärtigen six (zur Lösung von Problemen mit Metaklassen).
Es gibt jedoch auch einige Einschränkungen:
- Die Unterstützung von Python 3 umfasst Version 3.5 und höher (das Vorhandensein in Ihrem Projekt ist entweder ein Zeichen von Faulheit oder der Mangel an Notwendigkeit für Verbesserungen, da es schwer ist, einen objektiven Grund zu finden, warum Sie immer noch auf 3.4 sitzen);
- In Python 2.7 unterstützt die Bibliothek keine Deserialisierung von Set-Literalen. Beschreibung . Aber wenn jemand es implementieren möchte — willkommen:);
Die Bibliothek verwendet auch einen Ausnahmemechanismus für Parsing-Fehler. Wenn eine Zeile von keinem der vorhandenen Parser erkannt werden kann, bleibt der Wert als String (mehr aus Gründen der Bequemlichkeit und der Abwärtskompatibilität zur gewohnten Variablenlogik in Bash).
Die Bibliothek python-shell.
Nun erzähle ich von der zweiten Bibliothek (die Beschreibung der Mängel der vorhandenen Alternativen lasse ich weg — sie ähnelt der für smart-env. Alternativen — und ).
Insgesamt sind die Ideen für die Implementierung 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:
- Eine einheitliche Klasse, die Bash in der Python-Welt verkörpert;
- Jeder Bash-Befehl wird als Funktion der Klasse Shell aufgerufen;
- Die Parameter des Aufrufs jeder Funktion werden an den entsprechenden Bash-Befehl weitergegeben;
- Jeder Befehl wird "hier und jetzt" zum Zeitpunkt seines Aufrufs ausgeführt, d.h. es wird ein synchroner Ansatz verfolgt;
- Es besteht die Möglichkeit, den Ausgabeinhalt des Befehls im stdout sowie den Rückgabecode zu erhalten;
- Wenn der Befehl im System fehlt, wird eine Ausnahme ausgelöst.
Wie bereits bei smart-env gewährleistet, wird Python 2 unterstützt (obwohl dafür etwas mehr Opfertum benötigt wurde) und es wird kein Support für Python 3.0-3.4 angeboten.
Entwicklungspläne für die Bibliotheken
Die Bibliotheken können bereits jetzt verwendet werden: Beide sind auf dem offiziellen PyPI verfügbar. Quellcodes sind auf Github verfügbar (siehe unten).
Beide Bibliotheken werden unter Berücksichtigung des Feedbacks weiterentwickelt, das von Interessierten gesammelt wurde. Während es in smart-env vielleicht schwer ist, eine Vielzahl neuer Features zu finden, gibt es im python-shell definitiv noch viel hinzuzufügen:
- Unterstützung für nicht-blockierende Aufrufe;
- Möglichkeit zur interaktiven Kommunikation mit dem Befehl (Arbeiten mit stdin);
- Hinzufügen neuer Eigenschaften (z.B. eine Eigenschaft, um die Ausgabe aus stderr zu erhalten);
- Implementierung des Verzeichnisses verfügbarer Befehle (zur Verwendung mit der Funktion dir());
- usw.
Links
- Bibliothek smart-env: und
- Bibliothek python-shell: und
- Bibliotheksaktualisierungen
UPD 23.02.2020:
* Repositories wurden verschoben, die entsprechenden Links wurden aktualisiert
* Die Version python-shell==1.0.1 wird am 29.02.2020 veröffentlicht. Zu den Änderungen gehören die Unterstützung der automatischen Vervollständigung von Befehlen und der Befehl dir(Shell), die Ausführung von Befehlen mit ungültigen Python-Identifikatoren sowie Fehlerbehebungen.
Quelle: habr.com
