Jak analyzovat argumenty příkazového řádku v Pythonu

Chcete spouštět skripty Pythonu s argumenty příkazového řádku? Naučte se analyzovat argumenty příkazového řádku pomocí modulů sys, getopt a argparse v Pythonu.

Když v Pythonu chcete číst uživatelský vstup, použijete funkci input(). U některých aplikací však můžete chtít předat určité argumenty při spouštění skriptu na příkazovém řádku.

V tomto tutoriálu se naučíme, jak spustit skript Python s možnostmi a argumenty na příkazovém řádku. Poté se naučíme, jak používat vestavěné moduly Pythonu k analýze takových voleb a argumentů.

Pojďme začít!

Pochopení sys.argv v Pythonu

Pokud jste programovali v C, víte, že jedním z nejjednodušších způsobů předávání argumentů programu je příkazový řádek. Chcete-li tak učinit, můžete strukturovat hlavní funkci takto:

#include<stdio.h>

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

    return 0;
}

Zde argc znamená počet argumentů a argv znamená vektor argumentu.

Spouštění skriptů Python s argumenty příkazového řádku

V Pythonu můžete spustit skript Python na příkazovém řádku pomocí python3 filename.py. Přitom můžete také předat libovolný počet argumentů příkazového řádku:

$ python3 filename.py arg1 arg2 ... argn

Modul sys poskytuje přímou podporu pro přístup a zpracování těchto argumentů příkazového řádku. sys.argv je seznam všech argumentů příkazového řádku, které předáváme, když spouštíme skript Python.

Zde je příklad, kdy spouštíme main.py s argumenty příkazového řádku:

$ python3 main.py hello world python script

Můžeme procházet argumentový vektor pomocí jednoduchého cyklu for a funkce výčtu:

# 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

Vidíme, že první argument (na indexu 0) je název souboru Python. A následné argumenty začínají na indexu 1.

Toto je minimální pracovní program, který přijímá a zpracovává argumenty příkazového řádku. Vidíme však některé problémy:

  • Jak uživatelé programu vědí, jaké argumenty mají předat?
  • A co tyto argumenty znamenají?

To není moc jasné. K vyřešení tohoto problému můžete použít moduly getopt nebo argparse. A to se dozvíme v dalších dílech.✅

Analýza argumentů příkazového řádku pomocí getopt Pythonu

Pojďme se naučit, jak analyzovat argumenty příkazového řádku pomocí vestavěného modulu getopt.

Po importu getopt z modulu getopt můžete zadat argumenty k analýze a krátké volby a dlouhé volby, se kterými se má skript spustit. Musíme analyzovat všechny argumenty začínající na indexu 1 v sys.argv. Takže řez k analýze je sys.argv[1:].

  Jak opravit Microsoft Visual C++ Redistributable

Zde budeme potřebovat řetězec zprávy a název souboru. Použijme m a f jako krátké možnosti a zprávu a soubor jako dlouhé možnosti.

Jak ale zajistíme, že konkrétní možnost vyžaduje argument?

  • U krátkých voleb můžete nastavit, aby volba vyžadovala argument přidáním dvojtečky (:) za krátký název volby.
  • Podobně v dlouhých možnostech můžete za dlouhou možnost přidat znak =. Můžeme zachytit tyto možnosti a jejich příslušné argumenty.

Když je přidáme, budeme mít v main.py následující kód:

# main.py

import sys
from getopt import getopt

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

print(opts)
print(args)

Zde proměnná opts obsahuje možnosti a argumenty jako seznam n-tic. Jakýkoli další poziční argument, který předáme, bude shromážděn v proměnné args.

Můžeme předat zprávu a název souboru ke spuštění skriptu a můžeme použít buď krátké volby, nebo dlouhé volby.

Spuštěním main.py pomocí dlouhých možností máme:

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

Možnosti a argumenty máme jako n-tice v proměnné opts. Protože jsme nepředali žádný poziční argument, argumenty jsou prázdný seznam.

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

Ekvivalentně můžeme také použít krátké možnosti, jak je uvedeno:

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

⚠️ Krátkou volbu -m v tomto příkladu nelze zaměňovat s příznakem příkazového řádku -m, který se používá ke spuštění modulu jako hlavního modulu při spouštění skriptu Python.

Například použijete python3 -m unittest main.py ke spuštění unittestu jako hlavního modulu při spouštění main.py.

Zmínili jsme, že všechny ostatní poziční argumenty, které předáme, budou shromažďovány v proměnné args. Zde je příklad:

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

Seznam argumentů obsahuje poziční argument jiný_argument.

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

Zde je seznam n-tic. Můžeme to tedy procházet, rozbalit n-tici a vytáhnout argumenty odpovídající konkrétním možnostem.

Ale co uděláme s názvem souboru a zprávou poté, co zpracujeme tyto argumenty? Soubor otevřeme v režimu zápisu a do souboru zapíšeme řetězec zprávy převedený na velká písmena.

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

Spusťte main.py s krátkými možnostmi a argumenty příkazového řádku.

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

Po spuštění main.py můžeme vidět ‚thisfile.txt‘ v našem pracovním adresáři. Obsahuje řetězec ‚hello‘ převedený na velká písmena (‚HELLO‘).

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

Jak analyzovat argumenty příkazového řádku pomocí Argparse

Modul argparse, také zabudovaný do standardní knihovny Pythonu, poskytuje funkce pro analýzu argumentů příkazového řádku a také vytváření rozhraní příkazového řádku.

  7 nejlepších šablon agendy pro produktivnější jednání [2023]

Chcete-li analyzovat argumenty příkazového řádku, importujme třídu ArgumentParser z modulu argparse. Zde jsme vytvořili instanci arg_parser, objekt ArgumentParser:

from argparse import ArgumentParser

arg_parser = ArgumentParser()

Dále bychom chtěli přidat dva argumenty příkazového řádku:

  • zpráva: řetězec zprávy a
  • file: název souboru, se kterým chceme pracovat.

Nyní zavoláme metodu add_argument() na arg_parser, abychom přidali oba tyto argumenty. Ve volání metody add_argument() můžete nastavit help na řetězec (popis argumentu).

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

Doposud jsme vytvořili instanci arg_parser a přidali argumenty příkazového řádku. Když je program spuštěn na příkazovém řádku, můžete pomocí metody parse_args() na arg_parser získat hodnoty argumentů.

Zde zachytíme jmenný prostor argumentů v proměnné args. Hodnoty argumentů tedy můžete získat pomocí args.argument_name.

Po získání hodnot argumentů zapíšeme do souboru řetězec zprávy se zaměněnými velkými a malými písmeny (pomocí řetězcové metody swapcase()).

args = arg_parser.parse_args()

message = args.message
file = args.file

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

Když to všechno dáme dohromady, zde je náš soubor 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())

Pochopení použití argumentů příkazového řádku

Chcete-li porozumět použití argumentů při spuštění main.py, můžete použít volbu –help long, jak je znázorněno:

$ 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

Neexistují žádné volitelné argumenty a zpráva i soubor jsou povinné poziční argumenty. Alternativně můžete také použít krátkou volbu -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 je vidět, oba argumenty jsou ve výchozím nastavení pozičními argumenty. Pokud tedy nezadáte jeden nebo více z těchto argumentů, narazíte na chyby.

Zde jsme předali poziční argument (Ahoj) pro řetězec zprávy, ale nedodali jsme žádnou hodnotu pro argument souboru.

A dostaneme chybu oznamující, že je vyžadován argument souboru.

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

Když spustíme main.py s oběma pozičními argumenty, vidíme, že jmenný prostor args obsahuje hodnoty argumentů.

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

Nyní, když prozkoumáme obsah současného pracovního adresáře, uvidíme, že skript vytvoří soubor ‚file1.txt‘:

$ ls
file1.txt  main.py

Původní řetězec zprávy je ‚Ahoj‘; po záměně případu je řetězec zprávy v souboru ‚file1.txt‘ ‚hELLO‘.

$ cat file1.txt
hELLO

Jak nastavit argumenty příkazového řádku jako volitelné

Aby byly tyto argumenty příkazového řádku nepovinné, můžete před název argumentu uvést –.

  Jak přidat webovou stránku na domovskou obrazovku iPhonu nebo iPadu

Upravme main.py tak, aby byly argumenty zprávy i souboru nepovinné.

# main.py

from argparse import ArgumentParser

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

Protože oba argumenty příkazového řádku jsou volitelné, můžeme pro tyto argumenty nastavit výchozí hodnoty.

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

V tomto okamžiku obsahuje soubor main.py následující kód:

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

Pokud zkontrolujeme použití, uvidíme, že zpráva i soubor jsou nepovinné argumenty. To znamená, že nyní můžete spustit main.py bez obou těchto argumentů.

$ 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

V oboru názvů argumentů jsou soubor i zpráva Žádné.

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

Vidíme, že je použit výchozí název souboru a zpráva ‚myfile.txt‘ a ‚Python3‘. Soubor ‚myfile.txt‘ je nyní v pracovním adresáři:

$ ls
file1.txt  main.py  myfile.txt

A obsahuje řetězec ‚Python3‘ s prohozenými písmeny:

$ cat myfile.txt
pYTHON3

Můžete také použít oba argumenty –message a –file, aby byl příkaz čitelnější.

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

V pracovním adresáři vidíme soubor ‚file2.txt‘:

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

A podle očekávání obsahuje řetězec ‚coDING‘.

$ cat file2.txt
cODING

Závěr

Zde je souhrn toho, co jsme se naučili v tomto tutoriálu:

  • Podobně jako v programovacím jazyce C můžete v Pythonu přistupovat k argumentům příkazového řádku procházením argumentového vektoru sys.argv. sys.argv[0] je název skriptu Python. Takže nás zajímá analýza argumentů sys.argv[1:].
  • Chcete-li však zlepšit čitelnost a přidávat možnosti, můžete použít moduly getopt a argparse.
  • Pomocí modulu getopt můžete analyzovat seznam argumentů příkazového řádku počínaje indexem 1 až do konce seznamu. Můžete zadat krátké i dlouhé varianty.
  • Když volba přebírá argument, můžete zadat dvojtečku (:) a = za krátkou a dlouhou volbu.
  • S modulem argparse Pythonu můžete vytvořit instanci objektu ArgumentParser a použít metodu add_argument() k přidání požadovaného pozičního argumentu. Use — před názvem argumentu, aby byl volitelný.
  • Chcete-li načíst hodnoty argumentů příkazového řádku, zavolejte metodu parse_args() na objektu ArgumentParser.

Dále se naučte, jak provádět bezpečné hashování v Pythonu.