Argumente de linie de comandă în Python

Descriere

Python fiind un limbaj de programare foarte popular, precum și suport pentru majoritatea sistemelor de operare și multe biblioteci care facilitează procesarea argumentelor din linia de comandă - a devenit utilizat pe scară largă pentru a crea instrumente de linie de comandă în mai multe scopuri. Aceste instrumente pot varia de la simple aplicații CLI la cele care sunt mai complexe, cum ar fi AWS awscli instrument.

Instrumente complexe ca acesta sunt de obicei controlate de utilizator prin argumentele liniei de comandă, care permite utilizatorului să utilizeze anumite comenzi, să seteze opțiuni și multe altele. De exemplu, aceste opțiuni ar putea spune instrumentului să scoată informații suplimentare, să citească date dintr-o sursă specificată sau să trimită rezultate într-o anumită locație.

În general, argumentele sunt transmise instrumentelor CLI în mod diferit, în funcție de sistemul dvs. de operare:

  • asemănător Unix: - urmată de o scrisoare, ca -h, Sau -- urmat de un cuvânt, ca --help
  • Windows: / urmat fie de o literă, fie de un cuvânt, cum ar fi /help

Aceste abordări diferite există din motive istorice. Multe programe pe sisteme asemănătoare Unix acceptă atât notația liniuță simplă, cât și notația dublă. Notația cu o singură liniuță este folosită mai ales cu opțiuni cu o singură literă, în timp ce liniuțele duble prezintă o listă de opțiuni mai lizibilă, care este utilă în special pentru opțiunile complexe care trebuie să fie mai explicite.

notițe: În acest articol ne vom concentra numai pe formatul asemănător Unix al - și --.

Rețineți că atât numele, cât și semnificația unui argument sunt specifice unui program - nu există o definiție generală, în afară de câteva convenții comune precum --help pentru mai multe informații despre utilizarea instrumentului. În calitate de dezvoltator al unui script Python, veți decide ce argumente să furnizați apelantului și ce fac acesta. Acest lucru necesită o evaluare adecvată.

Pe măsură ce lista dvs. de argumente disponibile crește, codul dvs. va deveni mai complex în încercarea de a le analiza cu precizie. Din fericire, în Python există o serie de biblioteci disponibile pentru a vă ajuta în acest sens. Vom acoperi câteva dintre cele mai comune soluții, care variază de la „do-it-yourself” cu sys.argv, la abordarea „realizat pentru tine” cu argparse.

Gestionarea argumentelor liniei de comandă cu Python

Python 3+ și ecosistemul din jur acceptă o serie de moduri diferite de a gestiona argumentele liniei de comandă. Sunt multe biblioteci care fascilează analizarea argumentelor din linia de comandă.

Modul încorporat este de a utiliza sys modul. În ceea ce privește numele și utilizarea sa, se referă direct la biblioteca C (libc).

A doua cale este getopt modul, care gestionează atât opțiunile scurte cât și lungi, inclusiv evaluarea valorilor parametrilor.

modulul argparse, care este derivat din optparse modul (disponibil până la Python 2.7).

docopt modul, care este disponibil pe GitHub, permite de asemenea aceeași funcționalitate.

Recent, absl biblioteca a câștigat, de asemenea, abur, ca mijloc de înlocuire optparse și getopt().

Fiecare dintre aceste moduri are avantajele și dezavantajele lor, așa că merită să le evaluați pentru a vedea care se potrivește cel mai bine nevoilor dvs.

Modulul sys

Acesta este un modul de bază care a fost livrat cu Python din primele zile. Este nevoie de o abordare foarte similară cu utilizarea bibliotecii C argc/argv pentru a accesa argumentele. The modulul sys implementează argumentele liniei de comandă într-o structură simplă de listă numită sys.argv.

Fiecare element de listă reprezintă un singur argument. Primul articol din listă, sys.argv[0], este numele scriptului Python. Restul elementelor listei, sys.argv[1] la sys.argv[n], sunt argumentele liniei de comandă de la 2 la n.

Ca delimitator între argumente, se folosește un spațiu. Valorile argumentului care conțin un spațiu în el trebuie să fie înconjurate de ghilimele pentru a fi analizate corect de sys.

Echivalentul lui argc este doar numărul de elemente din listă. Pentru a obține această valoare, utilizați Python len() operator. Vom arăta acest lucru într-un exemplu de cod mai târziu.

Imprimarea primului argument CLI

În acest prim exemplu, scriptul nostru va determina modul în care a fost numit. Aceste informații sunt păstrate în primul argument de linie de comandă, indexat cu 0. Codul de mai jos arată cum obțineți numele scriptului dvs. Python:

import sys

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

Salvați acest cod într-un fișier numit arguments-program-name.py, apoi apelați-l așa cum se arată mai jos. Ieșirea este după cum urmează și conține numele fișierului, inclusiv calea completă:

$ 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

După cum puteți vedea din al doilea apel de mai sus, obținem nu numai numele fișierului Python, ci și calea completă folosită pentru a-l apela.

Numărarea numărului de argumente

În acest al doilea exemplu, pur și simplu numărăm numărul de argumente ale liniei de comandă folosind sistemul încorporat len() metodă. sys.argv este lista pe care trebuie să o examinăm. În codul de mai jos, obținem numărul de argumente și apoi scadem 1 deoarece unul dintre acele argumente (adică primul) este întotdeauna setat ca nume al fișierului, ceea ce nu ne este întotdeauna util. Astfel, numărul real de argumente transmise de utilizator este len(sys.argv) - 1:

import sys


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

Salvați și denumiți acest fișier arguments-count.py. Câteva exemple de apelare a acestui script sunt prezentate mai jos. Aceasta include trei scenarii diferite:

  • Un apel fără alte argumente în linia de comandă
  • Un apel cu două argumente
  • Un apel cu două argumente, în care al doilea este un șir ghilimeleu care conține un spațiu
$ 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
Iterarea prin argumente

Al treilea exemplu al nostru emite fiecare argument trimis către scriptul Python, cu excepția numelui programului însuși. Prin urmare, parcurgem argumentele liniei de comandă începând cu al doilea element de listă. Amintiți-vă că acesta este indexul 1, deoarece listele sunt bazate pe 0 în Python:

import sys


arguments = len(sys.argv) - 1


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

Mai jos numim codul nostru, care a fost salvat în fișierul arguments-output.py. După cum sa făcut cu exemplul nostru anterior, rezultatul ilustrează trei apeluri diferite:

  • Un apel fără argumente
  • Un apel cu două argumente
  • Un apel cu două argumente, unde al doilea argument este un șir între ghilimele care conține un spațiu
$ 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

Amintiți-vă, scopul de a afișa exemplul de șir citat este că parametrii sunt de obicei delimitați de un spațiu, dacă nu sunt înconjurate de ghilimele.

Steaguri de rappel (absl)

Biblioteca Flags a lui Abseil este menită să aducă argumente de linie de comandă în producție, cu argumente de linie de comandă distribuite. Când un modul folosește steaguri de linie de comandă și este importat într-un alt modul - celălalt modul importă și steagurile, și le poate procesa prin redirecționarea către modulul importat.

Acest lucru face ca argumentele complexe ale liniei de comandă partajate între module să fie mai ușor și mai puțin detaliate.

În plus, biblioteca vă permite să definiți valorile implicite, descrierile și tipul de date ale argumentelor, astfel încât verificări și conversii suplimentare nu sunt necesare.

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

Tipurile de date acceptate sunt:

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

Precum și DEFINE_multi_integer(), DEFINE_multi_string() și DEFINE_multi_enum() pentru introducerea cu mai multe argumente. În plus, alergare --help, --helpfull, etc. tipăriți steagurile existente și descrierile acestora, în diferite formate.

Consultați ghidul nostru practic și practic pentru a învăța Git, cu cele mai bune practici, standarde acceptate de industrie și fisa de cheat incluse. Opriți căutarea pe Google a comenzilor Git și de fapt învăţa aceasta!

Biblioteca vă permite, de asemenea, să definiți validări – atât în ​​termeni de interval, cum ar fi valorile bazate pe numere întregi având o upper_bound or lower_bound este acceptabil și rulează metode arbitrare pentru a verifica valorile:

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

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

Colectând acestea într-un exemplu concret:

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

Modulul argparse

modulul argparse a fost disponibil începând cu Python 3.2 și o îmbunătățire a optparse modul care există până la Python 2.7. Documentația Python conține o descriere API și un tutorial care acoperă toate metodele în detaliu.

Modulul oferă o interfață de linie de comandă cu o ieșire standardizată, în timp ce primele două soluții lasă o mare parte din muncă în mâinile tale. argparse permite verificarea argumentelor fixe și opționale, cu verificarea numelui ca stil scurt sau lung. Ca argument opțional implicit, acesta include -h, împreună cu versiunea sa lungă --help. Acest argument este însoțit de un mesaj implicit de ajutor care descrie argumentele acceptate.

Codul de mai jos arată inițializarea parserului, iar rezultatul de mai jos arată apelul de bază, urmat de mesajul de ajutor. Spre deosebire de apelurile Python pe care le-am folosit în exemplele anterioare, rețineți că folosiți Python 3 cu aceste exemple:


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

În pasul următor, vom adăuga o descriere personalizată la mesajul de ajutor pentru utilizatorii noștri. Inițializarea parserului în acest mod permite un text suplimentar. Codul de mai jos stochează descrierea în text variabilă, care este dată în mod explicit la argparse clasa ca description parametru. Apelând acest cod de mai jos, puteți vedea cum arată rezultatul:


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

Ca pas final vom adăuga un argument opțional numit -V, care are un argument de stil lung corespunzător numit --version. Pentru a face acest lucru folosim metoda add_argument() pe care îl numim cu trei parametri (afișați pentru --version, numai):

  • Numele parametrului: --version
  • Textul de ajutor pentru parametru: help="show program version"
  • Acțiune (fără valoare suplimentară): action="store_true"

Codul sursă pentru acesta este afișat mai jos. Citirea argumentelor în variabila numită args se face prin intermediul parse_args() metoda din parser obiect. Rețineți că trimiteți atât versiunea scurtă, cât și versiunea lungă într-un singur apel. În cele din urmă, verificați dacă atributele args.V or args.version sunt setate și scoate mesajul de versiune:


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 argumentul nu necesită ca o valoare să fie dată pe linia de comandă. De aceea am stabilit argumentul acțiunii la "store_true". În alte cazuri, este posibil să aveți nevoie de o valoare atribuită suplimentară, de exemplu dacă specificați un anumit volum, înălțime sau lățime. Acest lucru este prezentat în exemplul următor. Ca caz implicit, rețineți că toate argumentele sunt interpretate ca șiruri de caractere:


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)

Aici arătăm ce se întâmplă atunci când trimitem diferite valori de argument. Aceasta include atât versiunea scurtă, cât și cea lungă, precum și mesajul de ajutor:

$ 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

Modulul getopt

După cum probabil ați observat înainte, sys modul împarte șirul liniei de comandă numai în fațete individuale. Pitonul modul getopt merge puțin mai departe și extinde separarea șirului de intrare prin validarea parametrilor. Bazat pe getopt Funcția C, permite atât opțiuni scurte, cât și lungi, inclusiv o atribuire de valoare.

În practică, necesită sys modul pentru a procesa corect datele de intrare. Pentru a face acest lucru, atât sys modulul și getopt modulul trebuie încărcat în prealabil. Apoi, din lista parametrilor de intrare eliminăm primul element de listă (vezi codul de mai jos) și stocăm lista rămasă de argumente ale liniei de comandă în variabila numită argument_list:


import getopt, sys


full_cmd_arguments = sys.argv


argument_list = full_cmd_arguments[1:]

print argument_list

Argumentele din argument_list poate fi acum analizat folosind getopts() metodă. Dar înainte de a face asta, trebuie să spunem getopts() despre care parametri sunt validi. Ele sunt definite astfel:

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

Aceasta înseamnă că aceste argumente sunt cele pe care le considerăm valide, împreună cu câteva informații suplimentare:

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

S-ar putea să fi observat că o opțiunea scurtă a fost procedată de două puncte, :. Acest lucru spune getopt că acestei opțiuni ar trebui să i se atribuie o valoare.

Acest lucru ne permite acum să procesăm o listă de argumente. The getopt() metoda necesită configurarea a trei parametri – lista de argumente reale din argv, precum și atât opțiunile valide scurte cât și lungi (afișate în fragmentul de cod anterior).

Apelul de metodă în sine este păstrat într-o declarație try-catch pentru a acoperi erorile din timpul evaluării. O excepție este ridicată dacă este descoperit un argument care nu face parte din listă așa cum a fost definită anterior. Scriptul Python va imprima mesajul de eroare pe ecran și va ieși cu codul de eroare 2:

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

În cele din urmă, argumentele cu valorile corespunzătoare sunt stocate în cele două variabile numite arguments și values. Acum, puteți evalua cu ușurință aceste variabile în codul dvs. Putem folosi a for-buclă pentru a parcurge lista de argumente recunoscute, o intrare după alta.


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

Mai jos puteți vedea rezultatul executării acestui cod. Vom arăta cum reacționează programul atât cu argumentele programului valide, cât și cu cele nevalide:

$ 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

Ultimul apel către programul nostru poate părea puțin confuz la început. Pentru a o înțelege, trebuie să știți că opțiunile de prescurtare (uneori numite și steaguri) pot fi folosite împreună cu o singură liniuță. Acest lucru permite instrumentului dvs. să accepte mai ușor multe opțiuni. De exemplu, a suna python arguments-getopt.py -vh este la fel cu a suna python arguments-getopt.py -v -h. Deci, în ultimul apel de mai sus, getopt modul a crezut că utilizatorul încerca să treacă -e ca opțiune, care este invalidă.

Concluzie

În acest articol am arătat multe metode diferite pentru preluarea argumentelor liniei de comandă în Python, inclusiv utilizarea sys, getopt, și argparse. Aceste module variază în funcție de funcționalitate, unele oferind mult mai mult decât altele. sys este complet flexibil, în timp ce ambele getoptși argparse necesită o anumită structură. În schimb, ele acoperă cea mai mare parte a lucrărilor complexe care sys lasa la latitudinea ta. După ce ați analizat exemplele furnizate, ar trebui să puteți determina care modul se potrivește cel mai bine proiectului dvs.

În acest articol nu am vorbit despre alte soluții precum cea docopts modul, tocmai l-am menționat. Acest modul urmează o abordare total diferită și va fi explicat în detaliu într-unul dintre articolele următoare.

Referinte

Timestamp-ul:

Mai mult de la Stackabuse