Komentoriviargumentit Pythonissa

Yleiskatsaus

Python on erittäin suosittu ohjelmointikieli, ja se tukee useimpia käyttöjärjestelmiä ja monia kirjastoja, jotka tekevät komentoriviargumenttien käsittelystä helppoa. Sitä käytetään laajalti komentorivityökalujen luomiseen moniin tarkoituksiin. Nämä työkalut voivat vaihdella yksinkertaisista CLI-sovelluksista monimutkaisempiin, kuten AWS awscli työkalu.

Tämän kaltaisia ​​monimutkaisia ​​työkaluja hallitsee yleensä käyttäjä komentoriviargumentit, jonka avulla käyttäjä voi käyttää tiettyjä komentoja, asettaa asetuksia ja paljon muuta. Nämä vaihtoehdot voivat esimerkiksi käskeä työkalua tulostamaan lisätietoja, lukemaan tietoja tietystä lähteestä tai lähettämään tulosteen tiettyyn paikkaan.

Yleensä argumentit välitetään CLI-työkaluille eri tavalla käyttöjärjestelmästäsi riippuen:

  • Unix-tyyppinen: - sen jälkeen kirjain, esim -htai -- perässä sana, kuten --help
  • Windows: / sen jälkeen joko kirjain tai sana, kuten /help

Nämä erilaiset lähestymistavat ovat olemassa historiallisista syistä. Monet Unix-tyyppisten järjestelmien ohjelmat tukevat sekä yhden että kahden viivan merkintää. Yksiviivaista merkintää käytetään enimmäkseen yksikirjaimissa vaihtoehdoissa, kun taas kaksoisviivat tarjoavat luettavamman vaihtoehtoluettelon, mikä on erityisen hyödyllistä monimutkaisissa vaihtoehdoissa, joiden on oltava selkeämpiä.

Huomautuksia: Tässä artikkelissa keskitymme vain Unix-tyyppiseen muotoon - ja --.

Muista, että sekä argumentin nimi että merkitys ovat ohjelmakohtaisia ​​– yleistä määritelmää ei ole olemassa, lukuun ottamatta muutamia yleisiä käytäntöjä, kuten --help saadaksesi lisätietoja työkalun käytöstä. Python-skriptin kehittäjänä päätät, mitkä argumentit annat soittajalle ja mitä he tekevät. Tämä vaatii asianmukaista arviointia.

Kun käytettävissä olevien argumenttien luettelo kasvaa, koodistasi tulee monimutkaisempi yrittäessään jäsentää niitä tarkasti. Onneksi Pythonissa on useita kirjastoja, jotka auttavat sinua tässä. Käsittelemme muutamia yleisimpiä ratkaisuja, jotka vaihtelevat "tee-se-itse" -ratkaisuista sys.argv, "tehty sinulle" -lähestymistapaan argparse.

Komentoriviargumenttien käsittely Pythonilla

Python 3+ ja sen ympärillä oleva ekosysteemi tukevat useita erilaisia ​​tapoja käsitellä komentoriviargumentteja. On monet kirjastot, jotka kiehtovat komentoriviargumenttien jäsentämistä.

Sisäänrakennettu tapa on käyttää sys moduuli. Nimien ja käytön suhteen se liittyy suoraan C-kirjastoon (libc).

Toinen tapa on getopt moduuli, joka käsittelee sekä lyhyitä että pitkiä vaihtoehtoja, mukaan lukien parametrien arvojen arvioinnin.

- argparse-moduuli, joka on johdettu sanasta optparse moduuli (saatavilla Python 2.7 asti).

- docopt moduuli, joka on saatavilla GitHubissa, mahdollistaa myös saman toiminnon.

Äskettäin absl kirjasto on myös saanut voimaa korvaavana keinona optparse ja getopt().

Jokaisella näistä tavoista on hyvät ja huonot puolensa, joten kannattaa arvioida jokainen, mikä sopii tarpeisiisi parhaiten.

Sys-moduuli

Tämä on perusmoduuli, joka on toimitettu Pythonin kanssa alusta alkaen. Se käyttää hyvin samanlaista lähestymistapaa kuin C-kirjasto argc/argv päästä käsiksi argumentteihin. The sys-moduuli toteuttaa komentorivin argumentit yksinkertaisessa luettelorakenteessa nimeltä sys.argv.

Jokainen luetteloelementti edustaa yhtä argumenttia. Ensimmäinen kohta luettelossa, sys.argv[0], on Python-skriptin nimi. Muut luettelon elementit, sys.argv[1] että sys.argv[n], ovat komentorivin argumentit 2–n.

Argumenttien erottimena käytetään välilyöntiä. Argumenttiarvot, jotka sisältävät välilyönnin, on ympäröitävä lainausmerkeillä, jotta ne voidaan jäsentää oikein sys.

Vastaava argc on vain luettelon elementtien lukumäärä. Saat tämän arvon Pythonilla len() operaattori. Näytämme tämän koodiesimerkissä myöhemmin.

Ensimmäisen CLI-argumentin tulostaminen

Tässä ensimmäisessä esimerkissä skriptimme määrittää tavan, jolla sitä kutsuttiin. Nämä tiedot säilytetään ensimmäisessä komentoriviargumentissa, joka on indeksoitu 0:lla. Alla oleva koodi näyttää, kuinka saat Python-skriptisi nimen:

import sys

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

Tallenna tämä koodi tiedostoon nimeltä arguments-program-name.pyja kutsu sitä sitten alla olevan kuvan mukaisesti. Tulos on seuraava ja sisältää tiedoston nimen, mukaan lukien sen koko polku:

$ 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

Kuten näet yllä olevasta toisesta kutsusta, emme saa vain Python-tiedoston nimeä, vaan myös koko polun, jolla sitä kutsutaan.

Argumenttien lukumäärän laskeminen

Tässä toisessa esimerkissä laskemme yksinkertaisesti komentoriviargumenttien määrän käyttämällä sisäänrakennettua len() menetelmällä. sys.argv on luettelo, jota meidän on tutkittava. Alla olevassa koodissa saamme argumenttien lukumäärän ja vähennämme sitten 1, koska yksi argumenteista (eli ensimmäinen) asetetaan aina tiedoston nimeksi, mikä ei aina ole meille hyödyllistä. Siten käyttäjän välittämien argumenttien todellinen määrä on len(sys.argv) - 1:

import sys


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

Tallenna ja anna tälle tiedostolle nimi arguments-count.py. Alla on esimerkkejä tämän skriptin kutsumisesta. Tämä sisältää kolme erilaista skenaariota:

  • Kutsu ilman muita komentoriviargumentteja
  • Puhelu kahdella argumentilla
  • Kutsu kahdella argumentilla, joista toinen on lainausmerkkijono, joka sisältää välilyönnin
$ 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
Iterointi argumenttien kautta

Kolmas esimerkkimme tulostaa jokaisen Python-skriptiin lähetetyn argumentin paitsi itse ohjelman nimen. Siksi käymme läpi komentorivin argumentit alkaen toinen luetteloelementti. Muista, että tämä on indeksi 1, koska luettelot ovat Pythonissa 0-pohjaisia:

import sys


arguments = len(sys.argv) - 1


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

Alla kutsumme koodiamme, joka on tallennettu tiedostoon arguments-output.py. Kuten edellisessä esimerkissämme, tulos havainnollistaa kolmea erilaista kutsua:

  • Puhelu ilman perusteluja
  • Puhelu kahdella argumentilla
  • Kutsu kahdella argumentilla, jossa toinen argumentti on lainausmerkkijono, joka sisältää välilyönnin
$ 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

Muista, että lainatun merkkijonoesimerkin esittämisen tarkoitus on, että parametrit on yleensä rajattu välilyönnillä, ellei niitä ympäröivät lainaukset.

Abseil-liput (absl)

Abseilin Flags-kirjaston tarkoituksena on tuoda komentoriviargumentit tuotantoon jaettujen komentoriviargumenttien kanssa. Kun moduuli käyttää komentorivin lippuja ja se tuodaan toiseen moduuliin - toiseen moduuliin tuo myös liput maahan, ja voi käsitellä niitä lähettämällä ne edelleen tuotuun moduuliin.

Tämä tekee moduulien välillä jaetuista monimutkaisista komentoriviargumenteista helpompaa ja vähemmän monisanaista.

Lisäksi kirjastossa voit määrittää argumenttien oletusarvot, kuvaukset ja tietotyypit, joten lisätarkistuksia ja muunnoksia ei tarvita.

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}!")

Tuetut tietotyypit ovat:

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

Yhtä hyvin kuin DEFINE_multi_integer(), DEFINE_multi_string() ja DEFINE_multi_enum() usean argumentin syöttämiseen. Lisäksi juoksu --help, --helpfulljne. tulostaa olemassa olevat liput ja niiden kuvaukset eri muodoissa.

Tutustu käytännönläheiseen, käytännölliseen Gitin oppimisoppaaseemme, jossa on parhaat käytännöt, alan hyväksymät standardit ja mukana tuleva huijauslehti. Lopeta Git-komentojen googlailu ja oikeastaan oppia se!

Kirjastossa voit myös määrittää validointeja – sekä alueen suhteen, kuten kokonaislukupohjaiset arvot, joilla on upper_bound or lower_bound se on hyväksyttävää ja käyttää mielivaltaisia ​​menetelmiä arvojen tarkistamiseksi:

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

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

Kokoamalla nämä konkreettiseksi esimerkiksi:

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
...

argparse-moduuli

- argparse-moduuli on ollut saatavilla Python 3.2:sta lähtien, ja sen parannus optparse moduuli, joka on olemassa Python 2.7 asti. Python-dokumentaatio sisältää API-kuvauksen ja opetusohjelman, joka kattaa kaikki menetelmät yksityiskohtaisesti.

Moduuli tarjoaa komentoriviliittymän standardoidulla lähdöllä, kun taas kaksi edellistä ratkaisua jättävät suuren osan työstä sinun käsiisi. argparse mahdollistaa kiinteiden ja valinnaisten argumenttien varmentamisen ja nimentarkistuksen joko lyhyenä tai pitkänä tyylinä. Valinnaisena argumenttina se sisältää -h, yhdessä sen pitkän version kanssa --help. Tähän argumenttiin liittyy oletusapuviesti, joka kuvaa hyväksytyt argumentit.

Alla oleva koodi näyttää jäsentimen alustuksen ja alla oleva tulos, joka näyttää peruskutsun ja sen jälkeen ohjeviestin. Toisin kuin aiemmissa esimerkeissä käyttämiämme Python-kutsuja, muista käyttää Python 3:a näiden esimerkkien kanssa:


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

Seuraavassa vaiheessa lisäämme käyttäjillemme tarkoitettuun ohjeviestiin mukautetun kuvauksen. Jäsentimen alustaminen tällä tavalla mahdollistaa lisätekstin. Alla oleva koodi tallentaa kuvauksen text muuttuja, joka on nimenomaisesti annettu argparse luokka kuin description parametri. Kutsumalla tätä alla olevaa koodia voit nähdä, miltä tulos näyttää:


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

Viimeisenä vaiheena lisäämme valinnaisen argumentin nimeltä -V, jolla on vastaava pitkä tyyliargumentti nimeltä --version. Tätä varten käytämme menetelmää add_argument() jota kutsumme kolmella parametrilla (näytetään --version, vain):

  • Parametrin nimi: --version
  • Parametrin ohjeteksti: help="show program version"
  • Toimi (ilman lisäarvoa): action="store_true"

Sen lähdekoodi näkyy alla. Argumenttien lukeminen kutsuttuun muuttujaan args tehdään kautta parse_args() menetelmä parser esine. Huomaa, että lähetät sekä lyhyen että pitkän version yhdessä kutsussa. Lopuksi tarkistat, ovatko määritteet args.V or args.version on asetettu ja tulostaa versioviestin:


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

- --version argumentti ei edellytä arvon antamista komentorivillä. Siksi asetimme toiminta-argumentiksi "store_true". Muissa tapauksissa saatat tarvita lisäarvon, esimerkiksi jos määrität tietyn tilavuuden, korkeuden tai leveyden. Tämä näkyy seuraavassa esimerkissä. Oletustapauksena huomaa, että kaikki argumentit tulkitaan merkkijonoiksi:


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)

Tässä näytämme, mitä tapahtuu, kun lähetetään erilaisia ​​argumenttiarvoja. Tämä sisältää sekä lyhyen että pitkän version sekä ohjeviestin:

$ 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

Getopt-moduuli

Kuten olet ehkä huomannut aiemmin, sys moduuli jakaa komentorivimerkkijonon vain yksittäisiksi puoliksi. Python getopt-moduuli menee hieman pidemmälle ja laajentaa syötemerkkijonon erottelua parametrien validoinnilla. Perustuu getopt C-toiminto mahdollistaa sekä lyhyet että pitkät vaihtoehdot, mukaan lukien arvon määrityksen.

Käytännössä se edellyttää sys moduuli käsittelemään syötetyt tiedot oikein. Voit tehdä niin sekä sys moduuli ja getopt moduuli on ladattava etukäteen. Seuraavaksi poistamme syöttöparametrien luettelosta ensimmäisen listaelementin (katso koodi alla) ja tallennamme loput komentoriviargumenttien luettelosta muuttujaan nimeltä argument_list:


import getopt, sys


full_cmd_arguments = sys.argv


argument_list = full_cmd_arguments[1:]

print argument_list

Argumentit sisällä argument_list voidaan nyt jäsentää käyttämällä getopts() menetelmä. Mutta ennen kuin teemme sen, meidän on kerrottava getopts() mitkä parametrit ovat kelvollisia. Ne määritellään näin:

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

Tämä tarkoittaa, että pidämme näitä perusteluja pätevinä lisätietojen kera:

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

Olet ehkä huomannut, että o lyhyt vaihtoehto jatkui kaksoispisteellä, :. Tämä kertoo getopt että tälle vaihtoehdolle pitäisi antaa arvo.

Tämän avulla voimme nyt käsitellä luettelon argumenteista. The getopt() menetelmä vaatii kolmen parametrin määrittämisen – luettelon todellisista argumenteista argv, sekä sekä kelvolliset lyhyet että pitkät vaihtoehdot (näkyy edellisessä koodinpätkässä).

Itse menetelmäkutsu säilytetään try-catch-lauseessa arvioinnin aikana tapahtuneiden virheiden peittämiseksi. Poikkeus syntyy, jos löydetään argumentti, joka ei ole osa luetteloa, kuten aiemmin on määritelty. Python-skripti tulostaa virheilmoituksen näytölle ja poistuu virhekoodilla 2:

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

Lopuksi argumentit vastaavine arvoineen tallennetaan kahteen nimettyyn muuttujaan arguments ja values. Nyt voit helposti arvioida nämä muuttujat koodissasi. Voimme käyttää a for-silmukka toistaa tunnistettujen argumenttien luetteloa merkinnän jälkeen.


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))

Alla näet tämän koodin suorittamisen tuloksen. Näytämme, kuinka ohjelma reagoi sekä kelvollisilla että virheellisillä ohjelman argumenteilla:

$ 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

Ohjelmamme viimeinen kutsu saattaa aluksi tuntua hieman hämmentävältä. Ymmärtääksesi sen, sinun on tiedettävä, että pikakirjoitusvaihtoehtoja (joskus kutsutaan myös lipuiksi) voidaan käyttää yhdessä yhden viivan kanssa. Tämän ansiosta työkalusi hyväksyy helpommin monia vaihtoehtoja. Esimerkiksi soittamalla python arguments-getopt.py -vh on sama kuin soittaminen python arguments-getopt.py -v -h. Joten edellisessä yllä olevassa puhelussa getopt moduuli luuli, että käyttäjä yritti läpäistä -e vaihtoehtona, joka on virheellinen.

Yhteenveto

Tässä artikkelissa näytimme monia erilaisia ​​​​menetelmiä komentoriviargumenttien hakemiseen Pythonissa, mukaan lukien käyttö sys, getoptja argparse. Nämä moduulit vaihtelevat toiminnallisesti, ja jotkut tarjoavat paljon enemmän kuin toiset. sys on täysin joustava, kun taas molemmat getoptja argparse vaativat jonkinlaisen rakenteen. Sitä vastoin ne kattavat suurimman osan monimutkaisesta työstä sys jää sinun päätettäväksi. Kun olet työskennellyt annettujen esimerkkien läpi, sinun pitäisi pystyä määrittämään, mikä moduuli sopii parhaiten projektiisi.

Tässä artikkelissa emme puhuneet muista ratkaisuista, kuten docopts moduuli, mainitsimme sen juuri. Tämä moduuli noudattaa täysin erilaista lähestymistapaa, ja se selitetään yksityiskohtaisesti yhdessä seuraavista artikkeleista.

Viitteet

Aikaleima:

Lisää aiheesta Stackabus