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
getopt
aargparse
. - Modul
getopt
umožň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
argparse
nám umožňuje vytvořit instanciArgumentParser
a 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í.