Vriendschap tussen Python en Bash maken: smart-env- en python-shell-bibliotheken

Goedendag iedereen.

Tegenwoordig is Python een van de meest gebruikte talen op het gebied van het niet alleen maken van softwareproducten zelf, maar ook van het aanbieden van hun infrastructuur. Als gevolg hiervan moesten veel devops, met of zonder wil, een nieuwe taal leren om later te gebruiken als aanvulling op de goede oude Bash-scripts. Bash en Python belijden echter verschillende benaderingen bij het schrijven van code en hebben bepaalde kenmerken, wat betekent dat het overzetten van Bash-scripts naar de “slangentaal” soms een omvangrijke en verre van triviale taak blijkt te zijn.

Om het leven van ontwikkelaars gemakkelijker te maken, zijn er veel nuttige bibliotheken en hulpprogramma's in Python gemaakt en er worden nog steeds nieuwe gemaakt. Dit artikel beschrijft twee nieuwe bibliotheken die zijn gemaakt door de auteur van dit bericht: slimme omgeving и python-schaal - en ontworpen om ontwikkelaars te ontlasten van de noodzaak om veel aandacht te besteden aan de fijne kneepjes van het werken met Python, waardoor er ruimte overblijft voor interessantere taken. De reikwijdte van de activiteit van bibliotheken omvat omgevingsvariabelen en het lanceren van externe hulpprogramma's.

Iedereen die geïnteresseerd is, zie cat.

Nieuwe "fietsen"?

Het lijkt erop, waarom nieuwe pakketten maken voor redelijk gewone bewerkingen? Wat weerhoudt u ervan om os.environ en subprocess.<methode of klasse naar keuze> rechtstreeks te gebruiken?

Ik zal bewijs leveren ten gunste van elk van de bibliotheken afzonderlijk.

smart-env-bibliotheek

Voordat je je eigen geesteskind schrijft, is het handig om online te gaan zoeken naar kant-en-klare oplossingen. Natuurlijk bestaat het risico dat u niet vindt wat u nodig heeft, maar dit is eerder een “verzekeringsgebeurtenis”. Deze aanpak werkt in de regel en bespaart veel tijd en moeite.

Volgens de resultaten zoeken het volgende kwam naar voren:

  • er zijn pakketten die oproepen naar os.environ feitelijk inpakken, maar tegelijkertijd een aantal afleidende acties vereisen (het maken van een instantie van een klasse, speciale parameters in oproepen, enz.);
  • Er zijn goede pakketten, die echter strikt gebonden zijn aan een specifiek ecosysteem (voornamelijk webframeworks zoals Django) en daarom helemaal niet universeel zijn zonder bestand;
  • er zijn zeldzame pogingen om iets nieuws te doen. Bijvoorbeeld, typwerk toevoegen en expliciet variabele waarden parseren door methoden zoals
    get_<typename>(var_name)

    Of hier nog een oplossing, die echter de nu in ongenade gevallen Python 2 niet ondersteunt (die ondanks officiële RIPzijn er nog steeds bergen geschreven code en hele ecosystemen);

  • Er zijn ambachten van scholieren die om een ​​onbekende reden in de upstream PyPI terecht zijn gekomen en alleen maar problemen veroorzaken bij de naamgeving van nieuwe pakketten (met name de naam “smart-env” is een noodzakelijke maatregel).

En deze lijst kan nog lang doorgaan. De bovenstaande punten waren echter voldoende om mij enthousiast te maken voor het idee om iets handigs en universeels te maken.

Eisen die zijn gesteld vóór het schrijven van smart-env:

  • Het meest eenvoudige gebruiksschema
  • Eenvoudig configureerbare ondersteuning voor het typen van gegevens
  • Compatibel met Python 2.7
  • Goede codedekking door tests

Uiteindelijk is dit alles gerealiseerd. Hier is een voorbeeld van gebruik:

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

Zoals u in het voorbeeld kunt zien, hoeft u, om met een nieuwe klasse te werken, deze alleen maar te importeren (u hoeft geen instantie te maken - minus de extra actie). Toegang tot elke omgevingsvariabele wordt bereikt door ernaar te verwijzen als een variabele van de ENV-klasse, wat deze klasse in feite tot een intuïtieve verpakking voor de oorspronkelijke systeemomgeving maakt, terwijl deze tegelijkertijd wordt omgezet in een mogelijk configuratieobject voor vrijwel elk systeem ( een soortgelijke aanpak wordt bijvoorbeeld bereikt in Django , alleen daar is het configuratieobject de instellingenmodule/pakket zelf).

Het in-/uitschakelen van de automatische typeondersteuningsmodus wordt bereikt met behulp van twee methoden: enable_automatic_type_cast() en Disable_automatic_type_cast(). Dit kan handig zijn als de omgevingsvariabele een geserialiseerd JSON-achtig object bevat of zelfs alleen maar een Booleaanse constante (het expliciet instellen van de DEBUG-variabele in Django door de omgevingsvariabele te vergelijken met "geldige" tekenreeksen is een van de meest voorkomende gevallen). Maar nu is het niet meer nodig om strings expliciet te converteren - de meeste noodzakelijke acties zijn al diep in de bibliotheek ingebed en wachten alleen op een signaal om in actie te komen. 🙂 Over het algemeen werkt typen transparant en ondersteunt het bijna alle beschikbare ingebouwde gegevenstypen (frozenset, complex en bytes zijn niet getest).

De vereiste om Python 2 te ondersteunen werd vrijwel zonder opofferingen geïmplementeerd (het opgeven van typen en enkele van de “suikersnoepjes” van de nieuwste versies van Python 3), vooral dankzij de alomtegenwoordige zes (om de problemen van het gebruik van metaklassen op te lossen ).

Maar er zijn enkele beperkingen:

  • Ondersteuning voor Python 3 betekent versie 3.5 en hoger (hun aanwezigheid in uw project is het gevolg van luiheid of een gebrek aan behoefte aan verbeteringen, aangezien het moeilijk is om met een objectieve reden te komen waarom u nog steeds op 3.4 zit);
  • In Python 2.7 ondersteunt de bibliotheek geen deserialisatie van ingestelde letterlijke waarden. Beschrijving hier. Maar als iemand het wil implementeren, ben je welkom :);

De bibliotheek heeft ook een uitzonderingsmechanisme voor het geval van parseerfouten. Als de string niet herkend kan worden door een van de beschikbare analysatoren, blijft de waarde een string (eerder uit gemaksoverwegingen en achterwaartse compatibiliteit met de gebruikelijke logica van hoe variabelen werken in Bash).

Python-shell-bibliotheek

Nu zal ik je vertellen over de tweede bibliotheek (ik zal de beschrijving van de tekortkomingen van de bestaande analogen weglaten - deze is vergelijkbaar met die beschreven voor smart-env. Analogen - hier и hier).

Over het algemeen zijn het idee van implementatie en de vereisten daarvoor vergelijkbaar met die beschreven voor smart-env, zoals blijkt uit het voorbeeld:

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

Het idee is dit:

  1. Een enkele klasse die Bash vertegenwoordigt in de Python-wereld;
  2. Elk Bash-commando wordt aangeroepen als een functie van de Shell-klasse;
  3. De parameters voor elke functieaanroep worden vervolgens doorgegeven aan de overeenkomstige Bash-opdrachtaanroep;
  4. Elk commando wordt ‘hier en nu’ uitgevoerd op het moment dat het wordt aangeroepen, d.w.z. de synchrone aanpak werkt;
  5. het is mogelijk om toegang te krijgen tot de uitvoer van een commando in stdout, evenals de retourcode ervan;
  6. Als de opdracht niet in het systeem aanwezig is, wordt er een uitzondering gegenereerd.

Net als bij smart-env is er ondersteuning voor Python 2 (hoewel er wat meer opofferingsbloed nodig was) en geen ondersteuning voor Python 3.0-3.4.

Ontwikkelingsplannen voor de bibliotheek

U kunt de bibliotheken nu gebruiken: beide zijn op de officiële PyPI geplaatst. Bronnen zijn beschikbaar op Github (zie hieronder).

Beide bibliotheken zullen worden ontwikkeld rekening houdend met de feedback van geïnteresseerden. En als het misschien moeilijk is om een ​​verscheidenheid aan nieuwe functies in smart-env te bedenken, dan is er in python-shell zeker iets anders om toe te voegen:

  • ondersteuning voor niet-blokkerende oproepen;
  • mogelijkheid tot interactieve communicatie met het team (werken met stdin);
  • het toevoegen van nieuwe eigenschappen (bijvoorbeeld een eigenschap om uitvoer van stderr te ontvangen);
  • implementatie van een map met beschikbare opdrachten (voor gebruik met de functie dir());
  • etc.

referenties

  1. smart-env-bibliotheek: GitHub и PyPI
  2. Python-shell-bibliotheek: GitHub и PyPI
  3. Telegram-kanaal bibliotheek updates

UPD23.02.2020:
* Repository's zijn verplaatst, overeenkomstige links zijn bijgewerkt
* Versie python-shell==1.0.1 wordt voorbereid voor release op 29.02.2020-XNUMX-XNUMX. Veranderingen omvatten ondersteuning voor het automatisch aanvullen van opdrachten en de opdracht dir(Shell), het uitvoeren van opdrachten met een ongeldige Python-identifier en bugfixes.

Bron: www.habr.com

Voeg een reactie