Parancssori argumentumok Pythonban

Áttekintés

Mivel a Python nagyon népszerű programozási nyelv, valamint támogatja a legtöbb operációs rendszert és számos könyvtárat, amelyek megkönnyítik a parancssori argumentumok feldolgozását – széles körben használják számos célra parancssori eszközök létrehozására. Ezek az eszközök az egyszerű CLI-alkalmazásoktól a bonyolultabbakig, például az AWS-ig terjedhetnek. awscli eszköz.

Az ehhez hasonló összetett eszközöket általában a felhasználó vezérli parancssori argumentumokat, amely lehetővé teszi a felhasználó számára, hogy konkrét parancsokat, beállításokat stb. Ezek a beállítások például utasíthatják az eszközt, hogy további információkat adjon ki, adatokat olvasson be egy megadott forrásból, vagy küldjön kimenetet egy bizonyos helyre.

Az argumentumok általában eltérően kerülnek átadásra a CLI-eszközöknek, az operációs rendszertől függően:

  • Unix-szerű: - majd egy levél, mint pl -hvagy -- utána egy szó, mint --help
  • Windows: / vagy egy betű, vagy szó, mint például /help

Ezek a különböző megközelítések történelmi okok miatt léteznek. A Unix-szerű rendszereken sok program támogatja az egy- és kétkötőjeles jelölést. Az egykötőjeles jelölést többnyire egybetűs opciókkal használják, míg a dupla kötőjelek olvashatóbb opciókat jelenítenek meg, ami különösen hasznos olyan összetett opciók esetén, amelyeknek pontosabbnak kell lenniük.

Megjegyzések: Ebben a cikkben kizárólag a Unix-szerű formátumra fogunk összpontosítani - és a --.

Ne feledje, hogy az argumentum neve és jelentése is egy programra jellemző – nincs általános definíció, kivéve néhány általános konvenciót, mint pl. --help az eszköz használatával kapcsolatos további információkért. A Python-szkript fejlesztőjeként Ön dönti el, mely argumentumokat adja meg a hívónak, és mit tegyen. Ehhez megfelelő értékelésre van szükség.

Ahogy az elérhető argumentumok listája növekszik, a kód egyre összetettebb lesz a pontos elemzésük során. Szerencsére a Pythonban számos könyvtár áll rendelkezésre, amelyek segítenek ebben. Leírunk néhány leggyakoribb megoldást, a „csináld magad”-tól kezdve sys.argv, a „végzett érted” megközelítéshez argparse.

Parancssori argumentumok kezelése Python segítségével

A Python 3+ és a körülötte lévő ökoszisztéma számos különböző módot támogat a parancssori argumentumok kezelésére. Vannak sok könyvtárak, amelyek elbűvölik a parancssori argumentumok elemzését.

A beépített módja a sys modult. A neveket és a használatát tekintve közvetlenül kapcsolódik a C könyvtárhoz (libc).

A második út a getopt modul, amely mind a rövid, mind a hosszú opciókat kezeli, beleértve a paraméterértékek kiértékelését is.

A argparse modul, amely abból származik optparse modul (a Python 2.7-ig elérhető).

A docopt modult, ami az elérhető a GitHub-on, szintén lehetővé teszi ugyanazt a funkciót.

Nemrég a absl könyvtár is egyre nagyobb lendületet kapott, mint a pótlás eszköze optparse és a getopt().

Mindegyik módszernek megvannak a maga előnyei és hátrányai, ezért érdemes mindegyiket értékelni, hogy megtudja, melyik felel meg leginkább az Ön igényeinek.

A sys modul

Ez egy alapmodul, amelyet a kezdetektől a Pythonnal szállítottak. Nagyon hasonló megközelítést alkalmaz a C könyvtár használatához argc/argv hogy hozzáférjen az érvekhez. A sys modul nevű egyszerű listastruktúrában valósítja meg a parancssori argumentumokat sys.argv.

Minden listaelem egyetlen argumentumot képvisel. A lista első eleme, sys.argv[0], a Python szkript neve. A lista többi eleme, sys.argv[1] nak nek sys.argv[n], a parancssori argumentumok 2-től n-ig.

Az argumentumok közötti határolóként szóközt használunk. A szóközt tartalmazó argumentumértékeket idézőjelekkel kell körülvenni, hogy megfelelően értelmezhetőek legyenek sys.

A megfelelője argc csak a lista elemeinek száma. Ennek az értéknek a megszerzéséhez használja a Python-t len() operátor. Ezt a későbbiekben egy kódpéldán mutatjuk be.

Az első CLI-argumentum kinyomtatása

Ebben az első példában a szkriptünk határozza meg a hívás módját. Ezt az információt az első parancssori argumentum tárolja, 0-val indexelve. Az alábbi kód megmutatja, hogyan szerezheti meg Python-szkriptjének nevét:

import sys

print("The script has the name %s" % (sys.argv[0])

Mentse el ezt a kódot egy nevű fájlba arguments-program-name.py, majd hívja az alábbiak szerint. A kimenet a következő, és tartalmazza a fájl nevét, beleértve a teljes elérési utat:

$ python arguments-program-name.py
The script has the name arguments-program-name.py
$ python /home/user/arguments-program-name.py
The script has the name /home/user/arguments-program-name.py

Amint a fenti második hívásból is látható, nem csak a Python-fájl nevét kapjuk meg, hanem a teljes elérési utat is, amelyet annak hívására használnak.

Az érvek számának számolása

Ebben a második példában egyszerűen megszámoljuk a beépített parancssori argumentumok számát len() módszer. sys.argv ez a lista, amelyet meg kell vizsgálnunk. Az alábbi kódban megkapjuk az argumentumok számát, majd kivonjuk az 1-et, mert az egyik argumentum (azaz az első) mindig a fájl neveként van beállítva, ami nem mindig hasznos számunkra. Így a felhasználó által átadott argumentumok tényleges száma len(sys.argv) - 1:

import sys


arguments = len(sys.argv) - 1
print ("The script is called with %i arguments" % (arguments))

Mentse el és nevezze el ezt a fájlt arguments-count.py. Az alábbiakban látható néhány példa a szkript meghívására. Ez három különböző forgatókönyvet foglal magában:

  • Hívás további parancssori argumentumok nélkül
  • Felhívás két érvvel
  • Hívás két argumentummal, ahol a második egy szóközt tartalmazó idézőjeles karakterlánc
$ python arguments-count.py
The script is called with 0 arguments
$ python arguments-count.py --help me
The script is called with 2 arguments
$ python arguments-count.py --option "long string"
The script is called with 2 arguments
Ismétlés érvekkel

A harmadik példánk a Python-szkriptnek küldött összes argumentumot adja ki, kivéve magát a program nevét. Ezért a parancssori argumentumokat a következővel kezdjük második listaelem. Emlékezzünk vissza, hogy ez az index 1, mivel a listák Pythonban 0-alapúak:

import sys


arguments = len(sys.argv) - 1


position = 1
while (arguments >= position):
    print ("Parameter %i: %s" % (position, sys.argv[position]))
    position = position + 1

Az alábbiakban meghívjuk a kódunkat, amelyet az arguments-output.py fájlba mentettünk. Az előző példánkhoz hasonlóan a kimenet három különböző hívást mutat be:

  • Felhívás minden érv nélkül
  • Felhívás két érvvel
  • Hívás két argumentummal, ahol a második argumentum egy szóközt tartalmazó idézőjeles karakterlánc
$ python arguments-output.py
$ python arguments-output.py --help me
Parameter 1: --help
Parameter 2: me
$ python arguments-output.py --option "long string"
Parameter 1: --option
Parameter 2: long string

Ne feledje, az idézett karakterlánc-példa bemutatásának lényege az, hogy a paramétereket általában szóköz választja el, hacsak nem idézőjelek veszik körül.

Abseil zászlók (absl)

Az Abseil Flags könyvtárának célja, hogy parancssori argumentumokat vigyen a termelésbe, elosztott parancssori argumentumokkal. Amikor egy modul parancssori jelzőket használ, és egy másik modulba – a másik modulba – importálódik importálja a zászlókat is, és feldolgozhatja azokat az importált modulba való továbbítással.

Ez megkönnyíti és kevésbé bőbeszédűvé teszi a modulok között megosztott összetett parancssori argumentumokat.

Ezenkívül a könyvtár lehetővé teszi az argumentumok alapértelmezett értékeinek, leírásának és adattípusának meghatározását, így nincs szükség további ellenőrzésekre és átalakításokra.

from absl import flags
import sys


flags.DEFINE_string('name', 'User', 'The name of the user.')


FLAGS = flags.FLAGS
FLAGS(sys.argv)

print(f"Hello {FLAGS.name}!")

A támogatott adattípusok a következők:

  • DEFINE_integer()
  • DEFINE_string()
  • DEFINE_bool()
  • DEFINE_enum()
  • DEFINE_list()
  • DEFINE_float()

Szintén DEFINE_multi_integer(), DEFINE_multi_string() és a DEFINE_multi_enum() több argumentumú bevitelhez. Ráadásul futás --help, --helpfullstb. kinyomtathatja a meglévő zászlókat és azok leírását, különböző formátumokban.

Tekintse meg gyakorlatias, gyakorlati útmutatónkat a Git tanulásához, amely tartalmazza a bevált gyakorlatokat, az iparág által elfogadott szabványokat és a mellékelt csalólapot. Hagyd abba a guglizást a Git parancsokkal, és valójában tanulni meg!

A könyvtár lehetővé teszi érvényesítések meghatározását is – mind a tartomány tekintetében, mint például az egész szám alapú értékek, amelyek upper_bound or lower_bound ez elfogadható, és tetszőleges módszerek futtatása az értékek ellenőrzésére:

def validate_name(value):
    return len(value) > 15

flags.register_validator('name',
                         validate_name,
                         message='Name is over 15 characters long.',
                         flag_values=FLAGS)

Ezeket egy konkrét példába gyűjtve:

from absl import flags
import sys

flags.DEFINE_string('name', 'User', 'The name of the user.')
flags.DEFINE_integer('tasks', 0, 'The number of tasks a user has.', lower_bound=0)

FLAGS = flags.FLAGS
FLAGS(sys.argv)

print(f"{FLAGS.name} has {FLAGS.tasks} tasks to work on.")
$ python flags.py --name=John --tasks=5
John has 5 tasks to work on.
$ python flags.py --name=John --tasks=-1

Traceback (most recent call last):
  File "/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/site-packages/absl/flags/_flag.py", line 180, in _parse
    return self.parser.parse(argument)
  File "/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/site-packages/absl/flags/_argument_parser.py", line 168, in parse
    raise ValueError('%s is not %s' % (val, self.syntactic_help))
ValueError: -1 is not a non-negative integer
...

Az argparse modul

A argparse modul a Python 3.2 óta elérhető, és a optparse Python 2.7-ig létező modul. A Python dokumentációja tartalmaz egy API leírást és egy oktatóanyagot, amely részletesen lefedi az összes módszert.

A modul parancssori felületet kínál szabványos kimenettel, míg az előbbi két megoldás a munka nagy részét az Ön kezében hagyja. argparse lehetővé teszi a rögzített és opcionális argumentumok ellenőrzését, a névellenőrzést akár rövid, akár hosszú stílusban. Alapértelmezett opcionális argumentumként tartalmazza -h, annak hosszú változatával együtt --help. Ezt az argumentumot egy alapértelmezett súgóüzenet kíséri, amely leírja az elfogadott argumentumokat.

Az alábbi kód az elemző inicializálását mutatja, az alábbi kimenet pedig az alaphívást, majd a súgó üzenetet. Az előző példákban használt Python-hívásokkal ellentétben ne feledje, hogy a Python 3-at használja ezekkel a példákkal:


import argparse


parser = argparse.ArgumentParser()
parser.parse_args()
$ python3 arguments-argparse-basic.py 
$ python3 arguments-argparse-basic.py -h
usage: arguments-argparse-basic.py [-h]

optional arguments:
  -h, --help  show this help message and exit
$ python3 arguments-argparse-basic.py --verbose
usage: arguments-argparse-basic.py [-h]
arguments-argparse-basic.py: error: unrecognized arguments: --verbose

A következő lépésben egyéni leírást adunk a felhasználóinknak szóló súgóüzenethez. Az értelmező ilyen módon történő inicializálása további szöveget tesz lehetővé. Az alábbi kód a leírást a text változó, amely kifejezetten a argparse osztály, mint a description paraméter. Az alábbi kód meghívásával láthatja, hogyan néz ki a kimenet:


import argparse


text = 'This is a test program. It demonstrates how to use the argparse module with a program description.'


parser = argparse.ArgumentParser(description=text)
parser.parse_args()
$ python3 arguments-argparse-description.py --help
usage: arguments-argparse-description.py [-h]

This is a test program. It demonstrates how to use the argparse module with a
program description.

optional arguments:
  -h, --help  show this help message and exit

Utolsó lépésként egy opcionális argumentumot adunk hozzá -V, amelynek egy megfelelő hosszú stílusú argumentuma van --version. Ehhez a módszert használjuk add_argument() amelyet három paraméterrel hívunk meg (megjelenik a --version, csak):

  • A paraméter neve: --version
  • A paraméter súgószövege: help="show program version"
  • Művelet (kiegészítő érték nélkül): action="store_true"

Ennek forráskódja az alábbiakban látható. Az argumentumok beolvasása a meghívott változóba args keresztül történik parse_args() módszer a parser tárgy. Vegye figyelembe, hogy a rövid és a hosszú változatot is egy felhívásban küldje be. Végül ellenőrizze, hogy az attribútumok-e args.V or args.version be vannak állítva, és kiadják a verzióüzenetet:


import argparse


parser = argparse.ArgumentParser()
parser.add_argument("-V", "--version", help="show program version", action="store_true")


args = parser.parse_args()


if args.version:
    print("This is myprogram version 0.1")
$ python3 arguments-argparse-optional.py -V
This is myprogram version 0.1
$ python3 arguments-argparse-optional.py --version
This is myprogram version 0.1

A --version argumentumhoz nem szükséges értéket megadni a parancssorban. Ezért állítjuk be a cselekvési argumentumot "store_true". Más esetekben szükség lehet egy további hozzárendelt értékre, például ha megad egy bizonyos térfogatot, magasságot vagy szélességet. Ez látható a következő példában. Alapértelmezett esetként vegye figyelembe, hogy az összes argumentum karakterláncként értelmeződik:


import argparse


parser = argparse.ArgumentParser()


parser.add_argument("--width", "-w", help="set output width")


args = parser.parse_args()


if args.width:
    print("Set output width to %s" % args.width)

Itt bemutatjuk, mi történik különböző argumentumértékek megadásakor. Ez magában foglalja mind a rövid, mind a hosszú verziót, valamint a súgó üzenetet:

$ python3 arguments-argparse-optional2.py -w 10
Set output width to 10
$ python3 arguments-argparse-optional2.py --width 10
Set output width to 10
$ python3 arguments-argparse-optional2.py -h
usage: arguments-argparse-optional2.py [-h] [--width WIDTH]

optional arguments:
  -h, --help            show this help message and exit
  --width WIDTH, -w WIDTH
                        set output width

A getopt modul

Amint azt korábban észrevette, a sys modul csak egyetlen oldalra osztja fel a parancssori karakterláncot. A Python getopt modul egy kicsit tovább megy, és kiterjeszti a bemeneti karakterlánc elválasztását a paraméterek érvényesítésével. Alapján getopt C funkció, lehetővé teszi mind a rövid, mind a hosszú opciókat, beleértve az érték hozzárendelését.

A gyakorlatban megköveteli a sys modult a bemeneti adatok megfelelő feldolgozásához. Ehhez mind a sys modul és a getopt A modult előre be kell tölteni. Ezután a bemeneti paraméterek listájából eltávolítjuk az első listaelemet (lásd az alábbi kódot), és a parancssori argumentumok fennmaradó listáját tároljuk az ún. argument_list:


import getopt, sys


full_cmd_arguments = sys.argv


argument_list = full_cmd_arguments[1:]

print argument_list

Az érvek benne argument_list most elemezni lehet a getopts() módszer. De mielőtt ezt megtennénk, el kell mondanunk getopts() arról, hogy mely paraméterek érvényesek. Ezeket így határozzák meg:

short_options = "ho:v"
long_options = ["help", "output=", "verbose"]

Ez azt jelenti, hogy ezek az érvek azok, amelyeket érvényesnek tartunk, néhány további információval együtt:

------------------------------------------
long argument   short argument  with value
------------------------------------------
--help           -h              no
--output         -o              yes
--verbose        -v              no
------------------------------------------

Talán észrevetted, hogy a o A rövid opciót kettőspont követte, :. Ez azt mondja getopt hogy ehhez az opcióhoz értéket kell rendelni.

Ez most lehetővé teszi, hogy feldolgozzuk az érvek listáját. A getopt() metódus három paramétert igényel – a tényleges argumentumok listáját argv, valamint az érvényes rövid és hosszú opciókat is (az előző kódrészletben látható).

Maga a metódushívás try-catch-utasításban van tárolva, hogy fedezze a kiértékelés során előforduló hibákat. Kivételt jelent, ha a rendszer olyan argumentumot fedez fel, amely nem része a korábban meghatározott listának. A Python szkript kinyomtatja a hibaüzenetet a képernyőre, és kilép a 2-es hibakóddal:

try:
    arguments, values = getopt.getopt(argument_list, short_options, long_options)
except getopt.error as err:
    
    print (str(err))
    sys.exit(2)

Végül a megfelelő értékekkel rendelkező argumentumok a két megnevezett változóban tárolódnak arguments és a values. Most már könnyedén kiértékelheti ezeket a változókat a kódjában. Használhatunk a for-loop a felismert argumentumok listájának ismétléséhez, egyik bejegyzés a másik után.


for current_argument, current_value in arguments:
    if current_argument in ("-v", "--verbose"):
        print ("Enabling verbose mode")
    elif current_argument in ("-h", "--help"):
        print ("Displaying help")
    elif current_argument in ("-o", "--output"):
        print (("Enabling special output mode (%s)") % (current_value))

Az alábbiakban láthatja a kód végrehajtásának kimenetét. Megmutatjuk, hogyan reagál a program érvényes és érvénytelen program argumentumokkal:

$ python arguments-getopt.py -h
Displaying help
$ python arguments-getopt.py --help
Displaying help
$ python arguments-getopt.py --output=green --help -v
Enabling special output mode (green)
Displaying help
Enabling verbose mode
$ python arguments-getopt.py -verbose
option -e not recognized

A programunk utolsó hívása elsőre kissé zavarónak tűnhet. Ennek megértéséhez tudnia kell, hogy a gyorsírási opciók (néha zászlóknak is nevezik) egyetlen gondolatjellel együtt használhatók. Ez lehetővé teszi, hogy eszköze könnyebben elfogadjon számos lehetőséget. Például hívás python arguments-getopt.py -vh ugyanaz, mint hívni python arguments-getopt.py -v -h. Tehát a fenti utolsó hívásban a getopt modul úgy gondolta, hogy a felhasználó megpróbált átadni -e opcióként, ami érvénytelen.

Következtetés

Ebben a cikkben számos különböző módszert mutattunk be a parancssori argumentumok lekérésére a Pythonban, beleértve a használatát is sys, getoptés argparse. Ezeknek a moduloknak a funkcionalitása különbözik, egyesek sokkal többet nyújtanak, mint mások. sys teljesen rugalmas, míg mindkettő getoptés a argparse valamilyen struktúrát igényelnek. Ezzel szemben lefedik a legtöbb összetett munka, amely sys rajtad múlik. A bemutatott példák átdolgozása után meg kell tudnia határozni, hogy melyik modul felel meg a legjobban projektjének.

Ebben a cikkben nem beszéltünk más megoldásokról, mint pl docopts modult, most említettük. Ez a modul teljesen más megközelítést követ, és a következő cikkek egyikében részletesen ismertetjük.

Referenciák

Időbélyeg:

Még több Stackabus