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-h
tai--
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.py
ja 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
, --helpfull
jne. 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
, getopt
ja argparse
. Nämä moduulit vaihtelevat toiminnallisesti, ja jotkut tarjoavat paljon enemmän kuin toiset. sys
on täysin joustava, kun taas molemmat getopt
ja 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.