Freundschaft zwischen Python und Bash schließen: Smart-Env- und Python-Shell-Bibliotheken

Guten Tag an alle.

Heute ist Python eine der am häufigsten verwendeten Sprachen im Bereich der Erstellung nicht nur von Softwareprodukten selbst, sondern auch der Bereitstellung ihrer Infrastruktur. Infolgedessen mussten viele Entwickler, ob freiwillig oder gegen ihren Willen, eine neue Sprache lernen, um sie später als Ergänzung zu den guten alten Bash-Skripten zu verwenden. Allerdings verfolgen Bash und Python unterschiedliche Ansätze zum Schreiben von Code und verfügen über bestimmte Funktionen, sodass sich die Portierung von Bash-Skripten in die „Schlangensprache“ manchmal als umfangreiche und alles andere als triviale Aufgabe erweist.

Um Entwicklern das Leben zu erleichtern, wurden und werden weiterhin viele nützliche Bibliotheken und Dienstprogramme in Python erstellt. In diesem Artikel werden zwei neue Bibliotheken beschrieben, die vom Autor dieses Beitrags erstellt wurden: smart-env и Python-Shell - und wurde entwickelt, um Entwickler von der Notwendigkeit zu entlasten, den Feinheiten der Arbeit mit Python viel Aufmerksamkeit zu schenken, und um Raum für interessantere Aufgaben zu schaffen. Der Tätigkeitsbereich von Bibliotheken besteht aus Umgebungsvariablen und dem Starten externer Dienstprogramme.

Wer Interesse hat, schaut sich bitte die Katze an.

Neue „Fahrräder“?

Es scheint, warum sollte man neue Pakete für ganz normale Vorgänge erstellen? Was hindert Sie daran, os.environ und subprocess.<method or class of your choice> direkt zu verwenden?

Ich werde für jede der Bibliotheken gesondert Beweise vorlegen.

Smart-Env-Bibliothek

Bevor Sie Ihre eigene Idee schreiben, ist es sinnvoll, online nach vorgefertigten Lösungen zu suchen. Natürlich besteht die Gefahr, dass Sie nicht finden, was Sie brauchen, aber es handelt sich eher um einen „Versicherungsfall“. In der Regel funktioniert dieser Ansatz und spart viel Zeit und Aufwand.

Nach den Ergebnissen Suchen Folgendes wurde enthüllt:

  • Es gibt Pakete, die tatsächlich Aufrufe an os.environ umschließen, aber gleichzeitig eine Reihe ablenkender Aktionen erfordern (Erstellen einer Instanz einer Klasse, spezielle Parameter in Aufrufen usw.);
  • Es gibt gute Pakete, die jedoch streng an ein bestimmtes Ökosystem gebunden sind (hauptsächlich Web-Frameworks wie Django) und daher ohne Datei überhaupt nicht universell sind;
  • Es gibt selten Versuche, etwas Neues zu machen. Zum Beispiel, Tippen hinzufügen und Variablenwerte explizit analysieren, indem Methoden wie aufgerufen werden
    get_<typename>(var_name)

    Oder hier noch eine Lösung, das jedoch das inzwischen in Ungnade gefallene Python 2 nicht unterstützt (das, obwohl offizieller RIP, es gibt immer noch Berge von geschriebenem Code und ganze Ökosysteme);

  • Es gibt Schülerhandwerke, die aus unbekannten Gründen im Upstream-PyPI gelandet sind und nur Probleme bei der Benennung neuer Pakete verursachen (insbesondere der Name „smart-env“ ist eine notwendige Maßnahme).

Und diese Liste lässt sich noch lange fortführen. Die oben genannten Punkte reichten jedoch aus, um mich für die Idee zu begeistern, etwas Praktisches und Universelles zu schaffen.

Anforderungen, die vor dem Schreiben von smart-env festgelegt wurden:

  • Das einfachste Nutzungsschema
  • Leicht konfigurierbare Unterstützung für die Dateneingabe
  • Python 2.7 kompatibel
  • Gute Codeabdeckung durch Tests

Letztendlich wurde all dies realisiert. Hier ein Anwendungsbeispiel:

from smart_env import ENV

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

# assuming you set env variable MYVAR to "True"

ENV.enable_automatic_type_cast()

my_var = ENV.MY_VAR  # Equals boolean True

ENV.NEW_VAR = 100  # Sets a new environment variable

Wie Sie dem Beispiel entnehmen können, müssen Sie zum Arbeiten mit einer neuen Klasse diese nur importieren (Sie müssen keine Instanz erstellen – abzüglich der zusätzlichen Aktion). Der Zugriff auf jede Umgebungsvariable wird erreicht, indem man sie als Variable der ENV-Klasse bezeichnet, was diese Klasse tatsächlich zu einem intuitiven Wrapper für die native Systemumgebung macht und sie gleichzeitig in ein mögliches Konfigurationsobjekt für fast jedes System verwandelt ( Ein ähnlicher Ansatz wird beispielsweise in Django erreicht, nur dass dort das Konfigurationsobjekt das Einstellungsmodul/-paket selbst ist.

Das Aktivieren/Deaktivieren des automatischen Eingabeunterstützungsmodus erfolgt über zwei Methoden: enable_automatic_type_cast() und disable_automatic_type_cast(). Dies kann praktisch sein, wenn die Umgebungsvariable ein serialisiertes JSON-ähnliches Objekt oder auch nur eine boolesche Konstante enthält (das explizite Setzen der DEBUG-Variablen in Django durch Vergleichen der Umgebungsvariablen mit „gültigen“ Zeichenfolgen ist einer der häufigsten Fälle). Aber jetzt ist es nicht mehr nötig, Strings explizit zu konvertieren – die meisten notwendigen Aktionen sind bereits in den Tiefen der Bibliothek eingebettet und warten nur auf ein Signal zum Handeln. 🙂 Im Allgemeinen funktioniert die Eingabe transparent und unterstützt fast alle verfügbaren integrierten Datentypen (Frozenset, Complex und Bytes wurden nicht getestet).

Die Anforderung, Python 2 zu unterstützen, wurde praktisch ohne Abstriche umgesetzt (Verzicht auf das Tippen und einige der „Zuckerbonbons“ der neuesten Versionen von Python 3), insbesondere dank der allgegenwärtigen sechs (zur Lösung der Probleme bei der Verwendung von Metaklassen).

Es gibt jedoch einige Einschränkungen:

  • Python 3-Unterstützung bedeutet Version 3.5 und höher (ihre Präsenz in Ihrem Projekt ist entweder das Ergebnis von Faulheit oder mangelndem Verbesserungsbedarf, da es schwierig ist, einen objektiven Grund dafür zu finden, warum Sie immer noch auf 3.4 sind);
  • In Python 2.7 unterstützt die Bibliothek keine Deserialisierung von Mengenliteralen. Beschreibung hier. Aber wer es umsetzen möchte, ist herzlich willkommen :);

Die Bibliothek verfügt außerdem über einen Ausnahmemechanismus für den Fall von Parsing-Fehlern. Wenn die Zeichenfolge von keinem der verfügbaren Analysatoren erkannt werden konnte, bleibt der Wert eine Zeichenfolge (aus Gründen der Bequemlichkeit und der Abwärtskompatibilität mit der üblichen Logik, wie Variablen in Bash funktionieren).

Python-Shell-Bibliothek

Jetzt erzähle ich Ihnen von der zweiten Bibliothek (ich werde die Beschreibung der Mängel der vorhandenen Analoga weglassen – sie ähnelt der für Smart-Env. Analogues beschriebenen) hier и hier).

Generell ähneln die Idee der Umsetzung und die Anforderungen daran denen, die für smart-env beschrieben wurden, wie aus dem Beispiel hervorgeht:

from python_shell import Shell

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

command = Shell.whoami()  # Equals "whoami"
print(command.output)  # prints your current user name

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

Shell.mkdir('-p', '/tmp/new_folder')  # makes a new folder

Die Idee ist diese:

  1. Eine einzelne Klasse, die Bash in der Python-Welt repräsentiert;
  2. Jeder Bash-Befehl wird als Funktion der Shell-Klasse aufgerufen;
  3. Die Parameter für jeden Funktionsaufruf werden dann an den entsprechenden Bash-Befehlsaufruf übergeben;
  4. Jeder Befehl wird „hier und jetzt“ in dem Moment ausgeführt, in dem er aufgerufen wird, d. h. der synchrone Ansatz funktioniert;
  5. Es ist möglich, auf die Ausgabe eines Befehls in stdout sowie auf seinen Rückkehrcode zuzugreifen.
  6. Wenn der Befehl nicht im System vorhanden ist, wird eine Ausnahme ausgelöst.

Wie bei smart-env gibt es Unterstützung für Python 2 (obwohl etwas mehr Opferbereitschaft erforderlich war) und keine Unterstützung für Python 3.0-3.4.

Entwicklungspläne für die Bibliothek

Sie können die Bibliotheken jetzt nutzen: Beide sind auf dem offiziellen PyPI veröffentlicht. Quellen sind auf Github verfügbar (siehe unten).

Beide Bibliotheken werden unter Berücksichtigung des von Interessenten gesammelten Feedbacks entwickelt. Und wenn es schwierig sein mag, in smart-env eine Vielzahl neuer Funktionen zu entwickeln, dann gibt es in python-shell definitiv noch etwas hinzuzufügen:

  • Unterstützung für nicht blockierende Anrufe;
  • Möglichkeit der interaktiven Kommunikation mit dem Team (Arbeiten mit stdin);
  • Hinzufügen neuer Eigenschaften (z. B. Eigenschaft zum Empfangen der Ausgabe von stderr);
  • Implementierung eines Verzeichnisses verfügbarer Befehle (zur Verwendung mit der Funktion dir());
  • usw.

Referenzen

  1. Smart-Env-Bibliothek: Github и PyPI
  2. Python-Shell-Bibliothek: Github и PyPI
  3. Telegrammkanal Bibliotheksaktualisierungen

UPD 23.02.2020:
* Repositories wurden verschoben, entsprechende Links wurden aktualisiert
* Version python-shell==1.0.1 wird für die Veröffentlichung am 29.02.2020 vorbereitet. Zu den Änderungen gehören die Unterstützung der automatischen Befehlsvervollständigung und des Befehls dir(Shell), die Ausführung von Befehlen mit einer ungültigen Python-ID sowie Fehlerbehebungen.

Source: habr.com

Kommentar hinzufügen