Jak analizować argumenty wiersza poleceń w Pythonie

Chcesz uruchamiać skrypty Pythona z argumentami wiersza poleceń? Dowiedz się, jak analizować argumenty wiersza poleceń za pomocą modułów sys, getopt i argparse w języku Python.

W Pythonie, gdy chcesz wczytać dane wprowadzone przez użytkownika, użyjesz funkcji input(). Jednak w przypadku niektórych aplikacji możesz chcieć przekazać pewne argumenty podczas uruchamiania skryptu w wierszu poleceń.

W tym samouczku nauczymy się uruchamiać skrypt w języku Python z opcjami i argumentami w wierszu poleceń. Następnie nauczymy się, jak używać wbudowanych modułów Pythona do analizowania takich opcji i argumentów.

Zaczynajmy!

Zrozumienie sys.argv w Pythonie

Jeśli programowałeś w C, wiesz, że jednym z najprostszych sposobów przekazywania argumentów do programu jest wiersz poleceń. Aby to zrobić, możesz uporządkować główną funkcję w następujący sposób:

#include<stdio.h>

int main(int argc, char **argv){
    //argc: argument count
    //argv: argument vector
    
    //do something on the args

    return 0;
}

Tutaj argc oznacza liczbę argumentów, a argv oznacza wektor argumentów.

Uruchamianie skryptów Pythona z argumentami wiersza poleceń

W Pythonie możesz uruchomić skrypt Pythona w wierszu poleceń, używając python3 nazwa_pliku.py. Robiąc to, możesz również przekazać dowolną liczbę argumentów wiersza poleceń:

$ python3 filename.py arg1 arg2 ... argn

Moduł sys zapewnia natychmiastową obsługę dostępu i przetwarzania tych argumentów wiersza poleceń. sys.argv to lista wszystkich argumentów wiersza poleceń, które przekazujemy, gdy uruchamiamy skrypt Pythona.

Oto przykład, w którym uruchamiamy main.py z argumentami wiersza poleceń:

$ python3 main.py hello world python script

Możemy przejść przez wektor argumentów za pomocą prostej pętli for i funkcji wyliczającej:

# main.py

import sys

for idx, arg in enumerate(sys.argv):
    print(f"arg{idx}: {arg}")
# Output
arg0:main.py
arg1:hello
arg2:world
arg3:python
arg4:script

Widzimy, że pierwszym argumentem (w indeksie 0) jest nazwa pliku Pythona. Kolejne argumenty zaczynają się od indeksu 1.

Jest to minimalny działający program, który akceptuje i przetwarza argumenty wiersza poleceń. Widzimy jednak pewne problemy:

  • Skąd użytkownicy programu wiedzą, jakie argumenty przekazać?
  • I po co te argumenty?

To nie jest bardzo jasne. Aby rozwiązać ten problem, możesz użyć modułów getopt lub argparse. I tego dowiemy się w kolejnych sekcjach.✅

Analiza argumentów wiersza poleceń za pomocą getopt

Nauczmy się analizować argumenty wiersza poleceń za pomocą wbudowanego modułu getopt.

Po zaimportowaniu getopt z modułu getopt możesz określić argumenty do przeanalizowania oraz krótkie i długie opcje do uruchomienia skryptu. Musimy przeanalizować wszystkie argumenty zaczynające się od indeksu 1 w sys.argv. Tak więc wycinek do przeanalizowania to sys.argv[1:].

Tutaj będziemy potrzebować ciągu wiadomości i nazwy pliku. Użyjmy m i f jako opcji krótkich, a wiadomości i pliku jako opcji długich.

Ale jak upewnić się, że konkretna opcja wymaga argumentu?

  • W opcjach krótkich możesz sprawić, że opcja będzie wymagać argumentu, dodając dwukropek (:) po krótkiej nazwie opcji.
  • Podobnie w długich opcjach możesz dodać znak = po długiej opcji. Możemy uchwycić te opcje i odpowiadające im argumenty.

Dodając je, będziemy mieli następujący kod w main.py:

# main.py

import sys
from getopt import getopt

opts, args = getopt(sys.argv[1:],'m:f:',['message=","file="])

print(opts)
print(args)

Tutaj zmienna opts zawiera opcje i argumenty jako listę krotek. Każdy inny argument pozycyjny, który przekażemy, zostanie zebrany w zmiennej args.

Możemy przekazać wiadomość i nazwę pliku, aby uruchomić skrypt, i możemy użyć opcji krótkich lub długich.

Uruchamiając main.py przy użyciu długich opcji, mamy:

$ python3 main.py --message hello --file somefile.txt

Mamy opcje i argumenty jako krotki w zmiennej opts. Ponieważ nie przekazaliśmy żadnego argumentu pozycyjnego, args jest pustą listą.

# Output
[("--message', 'hello'), ('--file', 'somefile.txt')]
[]

Równoważnie możemy również użyć krótkich opcji, jak pokazano:

$ python3 main.py -m hello -f somefile.txt
# Output
[('-m', 'hello'), ('-f', 'somefile.txt')]
[]

⚠️ Opcji -m short w tym przykładzie nie należy mylić z flagą wiersza poleceń -m, która służy do uruchamiania modułu jako głównego modułu podczas uruchamiania skryptu Pythona.

Na przykład użyjesz python3 -m unittest main.py, aby uruchomić unittest jako główny moduł podczas uruchamiania main.py.

Wspomnieliśmy, że wszystkie inne przekazywane przez nas argumenty pozycyjne będą gromadzone w zmiennej args. Oto przykład:

$ python3 main.py -m hello -f somefile.txt another_argument

Lista argumentów zawiera argument pozycyjny inny_argument.

# Output
[('-m', 'hello'), ('-f', 'somefile.txt')]
['another_argument']

Tutaj opts to lista krotek. Możemy więc przejść przez nią, rozpakować krotkę i wyciągnąć argumenty odpowiadające określonym opcjom.

Ale co robimy z nazwą pliku i komunikatem po przetworzeniu tych argumentów? Otworzymy plik w trybie zapisu i zapiszemy do pliku ciąg wiadomości przekonwertowany na wielkie litery.

# main.py
import sys
from getopt import getopt

opts, args = getopt(sys.argv[1:],'m:f:',['message=","file="])

print(opts)
print(args)

for option, argument in opts:
    if option == "-m':
        message = argument
    if option == '-f':
        file = argument

with open(file,'w') as f:
    f.write(message.upper())

Uruchommy main.py z krótkimi opcjami i argumentami wiersza poleceń.

$ python main.py -m hello -f thisfile.txt
[('-m', 'hello'), ('-f', 'thisfile.txt')]
[]

Po uruchomieniu main.py możemy zobaczyć „thisfile.txt” w naszym katalogu roboczym. Zawiera ciąg „hello” przekonwertowany na wielkie litery („HELLO”).

$ ls
main.py  thisfile.txt
$ cat thisfile.txt
HELLO

Jak analizować argumenty wiersza poleceń za pomocą Argparse

Moduł argparse, również wbudowany w standardową bibliotekę Pythona, udostępnia funkcje analizowania argumentów wiersza poleceń, a także budowania interfejsów wiersza poleceń.

Aby przeanalizować argumenty wiersza poleceń, zaimportujmy klasę ArgumentParser z modułu argparse. Tutaj stworzyliśmy instancję arg_parser, obiektu ArgumentParser:

from argparse import ArgumentParser

arg_parser = ArgumentParser()

Następnie chcielibyśmy dodać dwa argumenty wiersza poleceń:

  • wiadomość: ciąg wiadomości i
  • plik: nazwa pliku, z którym chcielibyśmy pracować.

Teraz wywołujemy metodę add_argument() na arg_parser, aby dodać oba te argumenty. W wywołaniu metody add_argument() można ustawić pomoc na ciąg znaków (opis argumentu).

arg_parser.add_argument('message',help='message string')
arg_parser.add_argument('file',help='filename')

Do tej pory utworzyliśmy instancję arg_parser i dodaliśmy argumenty wiersza poleceń. Kiedy program jest uruchamiany z wiersza poleceń, możesz użyć metody parse_args() na arg_parser, aby uzyskać wartości argumentów.

Tutaj przechwytujemy przestrzeń nazw argumentów w zmiennej args. Możesz więc użyć args.argument_name, aby uzyskać wartości argumentów.

Po pobraniu wartości argumentów zapisujemy ciąg komunikatu z zamienioną wielkością liter (metodą łańcuchową swapcase()) do pliku.

args = arg_parser.parse_args()

message = args.message
file = args.file

with open(file,'w') as f:
     f.write(message.swapcase())

Łącząc to wszystko razem, oto nasz plik main.py:

# main.py

from argparse import ArgumentParser

arg_parser = ArgumentParser()
arg_parser.add_argument('message',help='message string')
arg_parser.add_argument('file',help='filename')

args = arg_parser.parse_args()
print(args)

message = args.message
file = args.file

with open(file,'w') as f:
     f.write(message.swapcase())

Zrozumienie użycia argumentów wiersza poleceń

Aby zrozumieć użycie argumentów podczas uruchamiania main.py, możesz użyć opcji –help long, jak pokazano:

$ python3 main.py --help
usage: main.py [-h] message file

positional arguments:
  message     message string
  file        filename

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

Nie ma opcjonalnych argumentów, a zarówno komunikat, jak i plik są wymaganymi argumentami pozycyjnymi. Alternatywnie możesz również użyć krótkiej opcji -h:

$ python3 main.py -h
usage: main.py [-h] message file

positional arguments:
  message     message string
  file        filename

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

Jak widać, oba argumenty są domyślnie argumentami pozycyjnymi. Więc jeśli nie przekażesz jednego lub więcej z tych argumentów, napotkasz błędy.

Tutaj przekazaliśmy argument pozycyjny (Hello) dla łańcucha wiadomości, ale nie podaliśmy żadnej wartości dla argumentu plik.

I pojawia się błąd informujący, że argument pliku jest wymagany.

$ python3 main.py Hello
usage: main.py [-h] message file
main.py: error: the following arguments are required: file

Kiedy uruchomimy main.py z obydwoma argumentami pozycyjnymi, zobaczymy, że przestrzeń nazw args zawiera wartości argumentów.

$ python3 main.py Hello file1.txt
# Output
Namespace(file="file1.txt", message="Hello")

Teraz, jeśli przyjrzymy się zawartości bieżącego katalogu roboczego, zobaczymy, że skrypt tworzy plik „file1.txt”:

$ ls
file1.txt  main.py

Oryginalny ciąg wiadomości to „Hello”; po zamianie wielkości liter ciąg komunikatu w pliku „file1.txt” to „hELLO”.

$ cat file1.txt
hELLO

Jak sprawić, by argumenty wiersza poleceń były opcjonalne

Aby uczynić te argumenty wiersza poleceń opcjonalnymi, możesz poprzedzić nazwę argumentu znakiem –.

Zmodyfikujmy plik main.py tak, aby zarówno komunikat, jak i argumenty pliku były opcjonalne.

# main.py

from argparse import ArgumentParser

arg_parser = ArgumentParser()
arg_parser.add_argument('--message',help='message string')
arg_parser.add_argument('--file',help='filename')

Ponieważ oba argumenty wiersza poleceń są opcjonalne, możemy ustawić wartości domyślne dla tych argumentów.

if args.message and args.file:
    message = args.message
    file = args.file
else:
    message="Python3"
    file="myfile.txt"

W tym momencie plik main.py zawiera następujący kod:

# main.py

from argparse import ArgumentParser

arg_parser = ArgumentParser()
arg_parser.add_argument('--message',help='message string')
arg_parser.add_argument('--file',help='filename')

args = arg_parser.parse_args()
print(args)

if args.message and args.file:
    message = args.message
    file = args.file
else:
    message="Python3"
    file="myfile.txt"

with open(file,'w') as f:
     f.write(message.swapcase())

Jeśli sprawdzimy użycie, zobaczymy, że zarówno komunikat, jak i plik są argumentami opcjonalnymi. Oznacza to, że możesz teraz uruchomić main.py bez obu tych argumentów.

$ python3 main.py --help
usage: main.py [-h] [--message MESSAGE] [--file FILE]

optional arguments:
  -h, --help         show this help message and exit
  --message MESSAGE  message string
  --file FILE        filename
$ python3 main.py

W przestrzeni nazw argumentów zarówno plik, jak i komunikat mają wartość Brak.

# Output
Namespace(file=None, message=None)

Widzimy, że używana jest domyślna nazwa pliku i komunikat „myfile.txt” i „Python3”. Plik „myfile.txt” znajduje się teraz w katalogu roboczym:

$ ls
file1.txt  main.py  myfile.txt

I zawiera ciąg „Python3” z zamienionymi literami:

$ cat myfile.txt
pYTHON3

Możesz także użyć zarówno argumentów –message, jak i –file, aby polecenie było bardziej czytelne.

$ python3 main.py --message Coding --file file2.txt
# Output
Namespace(file="file2.txt", message="Coding")

Widzimy „file2.txt” w katalogu roboczym:

$ ls
file1.txt  file2.txt  main.py  myfile.txt

I zgodnie z oczekiwaniami zawiera ciąg „coDING”.

$ cat file2.txt
cODING

Wniosek

Oto podsumowanie tego, czego nauczyliśmy się w tym samouczku:

  • Podobnie jak w języku programowania C, w Pythonie dostęp do argumentów wiersza poleceń można uzyskać, przechodząc przez wektor argumentów sys.argv. sys.argv[0] to nazwa skryptu Pythona. Jesteśmy więc zainteresowani analizowaniem argumentów sys.argv[1:].
  • Jednak aby zwiększyć czytelność i móc dodawać opcje, możesz użyć modułów getopt i argparse.
  • Możesz użyć modułu getopt do przeanalizowania listy argumentów wiersza poleceń, zaczynając od indeksu 1 aż do końca listy. Możesz określić zarówno krótkie, jak i długie opcje.
  • Kiedy opcja przyjmuje argument, możesz podać dwukropek (:) i = odpowiednio po krótkiej opcji i długiej opcji.
  • Za pomocą modułu argparse języka Python można utworzyć instancję obiektu ArgumentParser i użyć metody add_argument() w celu dodania wymaganego argumentu pozycyjnego. Użyj — przed nazwą argumentu, aby uczynić go opcjonalnym.
  • Aby pobrać wartości argumentów wiersza poleceń, wywołaj metodę parse_args() na obiekcie ArgumentParser.

Następnie dowiedz się, jak wykonać bezpieczne mieszanie w Pythonie.