Jak analyzovat argumenty příkazového řádku v Pythonu
Chcete-li spouštět skripty v Pythonu s využitím argumentů z příkazové řádky, je důležité umět je správně zpracovat. V tomto článku se podíváme, jak analyzovat tyto argumenty pomocí vestavěných modulů sys, getopt a argparse.
Běžně se uživatelský vstup získává pomocí funkce input(). Nicméně, pro některé aplikace je výhodnější předávat parametry přímo při spuštění skriptu z terminálu.
V následujícím textu si ukážeme, jak spustit skript Pythonu s různými možnostmi a argumenty z příkazové řádky. Naučíme se také využít vestavěné moduly Pythonu pro jejich efektivní analýzu.
Začněme!
Základy práce s sys.argv v Pythonu
Pokud máte zkušenosti s programováním v jazyce C, víte, že jedním z nejběžnějších způsobů, jak předat argumenty programu, je příkazová řádka. V C se to obvykle provádí strukturou hlavní funkce s parametry argc (počet argumentů) a argv (vektor argumentů), jak ukazuje následující kód:
#include<stdio.h>
int main(int argc, char **argv){
//argc: počet argumentů
//argv: vektor argumentů
//zpracování argumentů
return 0;
}
Zde argc reprezentuje celkový počet argumentů a argv je pole, které obsahuje jednotlivé argumenty.
Spouštění skriptů Pythonu s argumenty
V Pythonu můžete skript spustit z příkazové řádky pomocí příkazu python3 filename.py. K tomuto příkazu můžete připojit libovolný počet argumentů:
$ python3 filename.py arg1 arg2 ... argn
Modul sys poskytuje přímou podporu pro přístup a zpracování těchto argumentů. Konkrétně sys.argv je seznam obsahující všechny argumenty z příkazové řádky, které byly použity při spuštění skriptu.
Představme si, že spouštíme soubor main.py s několika argumenty:
$ python3 main.py hello world python script
K jednotlivým argumentům můžeme přistupovat pomocí cyklu for a funkce enumerate:
# main.py
import sys
for idx, arg in enumerate(sys.argv):
print(f"arg{idx}: {arg}")
# Výstup arg0: main.py arg1: hello arg2: world arg3: python arg4: script
Z výstupu je vidět, že první argument (na indexu 0) je samotný název spouštěného souboru Pythonu. Další argumenty následují od indexu 1.
Tímto způsobem lze poměrně snadno zpracovávat argumenty z příkazové řádky. Nicméně, existují i problémy, jako například:
- Jak uživatelé poznají, jaké argumenty mají předat?
- Jaký je význam jednotlivých argumentů?
Pro tyto situace je vhodné použít moduly getopt nebo argparse, což si ukážeme v následujících částech.
Analýza argumentů pomocí modulu getopt
Nyní se zaměříme na to, jak analyzovat argumenty příkazové řádky s využitím vestavěného modulu getopt.
Po importu modulu getopt, můžeme specifikovat argumenty, které se mají analyzovat, a to včetně krátkých a dlouhých voleb. Pro analýzu se používá část sys.argv od indexu 1, tedy sys.argv[1:].
Předpokládejme, že chceme mít možnost zadat zprávu a název souboru. Pro krátké volby použijeme m pro zprávu a f pro soubor, pro dlouhé volby message a file.
Otázkou je, jak definovat, že konkrétní volba vyžaduje argument:
- U krátkých voleb se to provede přidáním dvojtečky (:) za název volby.
- U dlouhých voleb se za název přidá znak rovnítka (=).
Náš kód v souboru main.py bude vypadat následovně:
# main.py import sys from getopt import getopt opts, args = getopt(sys.argv[1:],'m:f:',['message=','file=']) print(opts) print(args)
Proměnná opts bude obsahovat seznam n-tic s volbami a jejich argumenty. V proměnné args pak budou zbylé poziční argumenty.
Při spuštění skriptu můžeme zadat jak krátké, tak i dlouhé volby.
Například spuštění s dlouhými volbami:
$ python3 main.py --message hello --file somefile.txt
Výsledkem je, že opts obsahuje n-tice s volbami a args je prázdný seznam, protože nebyly předány žádné další poziční argumenty.
# Výstup
[('--message', 'hello'), ('--file', 'somefile.txt')]
[]
Stejně tak můžeme použít i krátké volby:
$ python3 main.py -m hello -f somefile.txt
# Výstup
[('-m', 'hello'), ('-f', 'somefile.txt')]
[]
⚠️ Je důležité si uvědomit, že krátká volba -m se v tomto příkladu nesmí zaměňovat s příznakem příkazové řádky -m, který se používá pro spuštění modulu jako hlavního modulu.
Jak jsme zmínili, všechny poziční argumenty, které nepředcházejí volby, se shromáždí v proměnné args. Podívejme se na příklad:
$ python3 main.py -m hello -f somefile.txt another_argument
V tomto případě seznam argumentů obsahuje položku another_argument.
# Výstup
[('-m', 'hello'), ('-f', 'somefile.txt')]
['another_argument']
Seznam opts obsahuje n-tice, které můžeme iterovat a extrahovat hodnoty argumentů pro specifické volby.
Nyní si ukážeme, jak můžeme využít tyto argumenty. Otevřeme soubor v režimu zápisu a zapíšeme do něj zprávu převedenou 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())
Nyní spustíme main.py s krátkými volbami a argumenty:
$ python3 main.py -m hello -f thisfile.txt
[('-m', 'hello'), ('-f', 'thisfile.txt')]
[]
Po spuštění se v pracovním adresáři objeví soubor thisfile.txt, který bude obsahovat text HELLO.
$ ls main.py thisfile.txt
$ cat thisfile.txt HELLO
Analýza argumentů pomocí modulu argparse
Modul argparse, který je také součástí standardní knihovny Pythonu, je dalším nástrojem pro analýzu argumentů z příkazové řádky. Poskytuje navíc i funkce pro tvorbu uživatelsky přívětivého rozhraní.
Pro analýzu je nutné importovat třídu ArgumentParser. Následně vytvoříme její instanci, nazvanou například arg_parser:
from argparse import ArgumentParser arg_parser = ArgumentParser()
Dále definujeme dva argumenty: message (zprávu) a file (název souboru).
Pro přidání argumentů použijeme metodu add_argument(). Ve volání této metody můžeme specifikovat popis argumentu pomocí parametru help.
arg_parser.add_argument('message',help='Zpráva')
arg_parser.add_argument('file',help='Název souboru')
Po vytvoření instance arg_parser a přidání argumentů můžeme získat hodnoty argumentů pomocí metody parse_args(), která se volá na objektu arg_parser.
Hodnoty argumentů se uloží do proměnné args a můžeme k nim přistupovat pomocí syntaxe args.argument_name.
Po získání argumentů, zapíšeme zprávu do souboru, s prohozenými velkými a malými písmeny (pomocí metody swapcase()).
args = arg_parser.parse_args()
message = args.message
file = args.file
with open(file,'w') as f:
f.write(message.swapcase())
Kompletní soubor main.py vypadá takto:
# main.py
from argparse import ArgumentParser
arg_parser = ArgumentParser()
arg_parser.add_argument('message',help='Zpráva')
arg_parser.add_argument('file',help='Název souboru')
args = arg_parser.parse_args()
print(args)
message = args.message
file = args.file
with open(file,'w') as f:
f.write(message.swapcase())
Základy použití argumentů z příkazové řádky
Abychom pochopili, jak se používají argumenty při spuštění main.py, můžeme použít volbu --help, jak je uvedeno níže:
$ python3 main.py --help usage: main.py [-h] message file positional arguments: message Zpráva file Název souboru optional arguments: -h, --help Zobrazí tuto nápovědu a ukončí program
Z výstupu je patrné, že neexistují žádné volitelné argumenty a jak zpráva, tak soubor jsou povinné poziční argumenty. Alternativně můžete použít i krátkou volbu -h:
$ python3 main.py -h usage: main.py [-h] message file positional arguments: message Zpráva file Název souboru optional arguments: -h, --help Zobrazí tuto nápovědu a ukončí program
Oba argumenty jsou tedy poziční, a pokud je nevyplníme, dojde k chybě.
V následujícím příkladu předáme poziční argument (Ahoj) pro zprávu, ale nepředáme žádný argument pro soubor:
$ python3 main.py Ahoj usage: main.py [-h] message file main.py: error: the following arguments are required: file
Jakmile předáme oba poziční argumenty, můžeme vidět, že jmenný prostor args obsahuje jejich hodnoty:
$ python3 main.py Ahoj file1.txt
# Výstup Namespace(file='file1.txt', message='Ahoj')
Po spuštění skriptu se v pracovním adresáři objeví soubor file1.txt:
$ ls file1.txt main.py
A jeho obsah bude řetězec Ahoj s prohozenými písmeny, tedy aHOJ:
$ cat file1.txt aHOJ
Jak nastavit argumenty jako volitelné
Chceme-li, aby argumenty byly volitelné, musíme před název argumentu přidat --.
Upravme main.py tak, aby byly argumenty zprávy i souboru volitelné:
# main.py
from argparse import ArgumentParser
arg_parser = ArgumentParser()
arg_parser.add_argument('--message',help='Zpráva')
arg_parser.add_argument('--file',help='Název souboru')
Protože oba argumenty jsou nyní volitelné, můžeme pro ně nastavit výchozí hodnoty:
if args.message and args.file:
message = args.message
file = args.file
else:
message="Python3"
file="myfile.txt"
Kompletní main.py nyní vypadá takto:
# main.py
from argparse import ArgumentParser
arg_parser = ArgumentParser()
arg_parser.add_argument('--message',help='Zpráva')
arg_parser.add_argument('--file',help='Název souboru')
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())
Při kontrole nápovědy uvidíme, že zpráva i soubor jsou nyní volitelné, což znamená, že můžeme spustit main.py bez jakýchkoli argumentů.
$ python3 main.py --help usage: main.py [-h] [--message MESSAGE] [--file FILE] optional arguments: -h, --help Zobrazí tuto nápovědu a ukončí program --message MESSAGE Zpráva --file FILE Název souboru
$ python3 main.py
Pokud nebyly zadány žádné argumenty, hodnoty souboru i zprávy budou None:
# Výstup Namespace(file=None, message=None)
V takovém případě se použije výchozí zpráva Python3 a název souboru myfile.txt. V pracovním adresáři tak vznikne soubor myfile.txt:
$ ls file1.txt main.py myfile.txt
Obsah souboru bude řetězec Python3 s prohozenými písmeny:
$ cat myfile.txt pYTHON3
Můžeme také použít argumenty --message a --file pro lepší čitelnost příkazu:
$ python3 main.py --message Coding --file file2.txt
# Výstup Namespace(file='file2.txt', message='Coding')
V pracovním adresáři se objeví nový soubor file2.txt:
$ ls file1.txt file2.txt main.py myfile.txt
A jeho obsahem bude text coDING:
$ cat file2.txt cODING
Závěr
V tomto tutoriálu jsme si ukázali, jak pracovat s argumenty příkazové řádky v Pythonu. Zde je krátký souhrn klíčových bodů:
- Stejně jako v jazyce C, i v Pythonu můžeme přistupovat k argumentům z příkazové řádky prostřednictvím seznamu
sys.argv. Položkasys.argv[0]je název spouštěného skriptu, proto nás zajímá analýza argumentů odsys.argv[1:]. - Pro lepší čitelnost a možnost definování voleb lze využít moduly
getoptaargparse. - Modul
getoptumožňuje analyzovat seznam argumentů od indexu 1. Můžeme definovat jak krátké, tak i dlouhé volby. - Pokud volba vyžaduje argument, přidáme za její název dvojtečku (:) u krátkých voleb a rovnítko (=) u dlouhých voleb.
- Modul
argparsenám umožňuje vytvořit instanciArgumentParsera použít metoduadd_argument()k přidávání pozičních argumentů. Pro definování volitelných argumentů se před jejich názvy v metoděadd_argument()vkládá--. - Hodnoty argumentů lze načíst voláním metody
parse_args()na instanciArgumentParser.
V budoucnu se podíváme na další témata spojená s Pythonem, například na bezpečné hashování.