Как да анализирате аргументите на командния ред в Python

Искате ли да изпълнявате скриптове на Python с аргументи от командния ред? Научете как да анализирате аргументите на командния ред с помощта на модулите sys, getopt и argparse в Python.

В Python, когато искате да прочетете въведеното от потребителя, ще използвате функцията input(). За някои приложения обаче може да искате да предадете определени аргументи, докато изпълнявате скрипта в командния ред.

В този урок ще научим как да изпълняваме скрипт на Python с опции и аргументи в командния ред. След това ще научим как да използваме вградените модули на Python, за да анализираме такива опции и аргументи.

Нека да започнем!

Разбиране на sys.argv в Python

Ако сте програмирали на C, знаете, че един от най-лесните начини за предаване на аргументи към програмата е чрез командния ред. За да направите това, можете да структурирате основната функция така:

#include<stdio.h>

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

    return 0;
}

Тук argc означава брой аргументи, а argv означава вектор на аргументи.

Изпълнение на Python скриптове с аргументи от командния ред

В Python можете да стартирате скрипта на Python в командния ред, като използвате python3 filename.py. Когато правите това, можете също да подадете произволен брой аргументи от командния ред:

$ python3 filename.py arg1 arg2 ... argn

Модулът sys предоставя поддръжка извън кутията за достъп и обработка на тези аргументи на командния ред. sys.argv е списъкът с всички аргументи на командния ред, които предаваме, когато изпълняваме скрипта на Python.

Ето пример, в който изпълняваме main.py с аргументи от командния ред:

$ python3 main.py hello world python script

Можем да преминем през вектора на аргумента, като използваме проста функция за цикъл и изброяване:

# 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

Виждаме, че първият аргумент (с индекс 0) е името на Python файла. Следващите аргументи започват от индекс 1.

Това е минимална работеща програма, която приема и обработва аргументи от командния ред. Виждаме обаче някои проблеми:

  • Как потребителите на програмата знаят какви аргументи да подадат?
  • И какво означават тези аргументи?

Това не е много ясно. За да разрешите това, можете да използвате модулите getopt или argparse. И ще научим това в следващите раздели.✅

Разбор на аргументи от командния ред с помощта на getopt на Python

Нека научим как да анализираме аргументите на командния ред с помощта на вградения модул getopt.

  Как автоматично да отваряте връзки в Chrome на iPhone и iPad

След като импортирате getopt от модула getopt, можете да посочите аргументите за анализиране и кратките опции и дългите опции, с които да стартирате скрипта. Трябва да анализираме всички аргументи, започващи от индекс 1 в sys.argv. Така че срезът за анализ е sys.argv[1:].

Тук ще ни трябва низ за съобщение и име на файл. Нека използваме m и f като кратки опции и съобщение и файл като дълги опции.

Но как да гарантираме, че конкретна опция изисква аргумент?

  • В кратките опции можете да накарате опция да изисква аргумент, като добавите двоеточие (:) след краткото име на опцията.
  • По подобен начин в дългите опции можете да добавите знак = след дългата опция. Можем да уловим тези опции и съответните им аргументи.

Добавяйки ги, ще имаме следния код в main.py:

# main.py

import sys
from getopt import getopt

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

print(opts)
print(args)

Тук променливата opts съдържа опциите и аргументите като списък от кортежи. Всеки друг позиционен аргумент, който предаваме, ще бъде събран в променлива args.

Можем да предадем съобщението и името на файла, за да стартираме скрипта, и можем да използваме или кратките опции, или дългите опции.

Изпълнявайки main.py с дългите опции, имаме:

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

Имаме опциите и аргументите като кортежи в променливата opts. Тъй като не сме предали нито един позиционен аргумент, args е празен списък.

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

По същия начин можем да използваме и кратките опции, както е показано:

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

⚠️ Кратката опция -m в този пример не трябва да се бърка с флага на командния ред -m, който се използва за изпълнение на модул като основен модул при изпълнение на скрипт на Python.

Например ще използвате python3 -m unittest main.py, за да стартирате unittest като основен модул, когато изпълнявате main.py.

Споменахме, че всички други позиционни аргументи, които предаваме, ще бъдат събрани в променливата args. Ето един пример:

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

Списъкът с аргументи съдържа позиционния аргумент other_argument.

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

Тук opts е списък от кортежи. Така че можем да преминем през него, да разопаковаме кортежа и да извадим аргументите, съответстващи на конкретните опции.

Но какво правим с името на файла и съобщението, след като сме обработили тези аргументи? Ще отворим файла в режим на запис и ще запишем низа на съобщението, преобразуван в главни букви, във файла.

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

Нека стартираме main.py с кратките опции и аргументите на командния ред.

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

След като стартираме main.py, можем да видим ‘thisfile.txt’ в нашата работна директория. Той съдържа низа ‘hello’, преобразуван в главни букви (‘HELLO’).

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

Как да анализирате аргументите на командния ред с Argparse

Модулът argparse, също вграден в стандартната библиотека на Python, предоставя функционалност за анализиране на аргументи на командния ред и също така изграждане на интерфейси на командния ред.

  Можете ли да влезете в акаунта си за PS4 на друга PS4?

За да анализираме аргументите на командния ред, нека импортираме класа ArgumentParser от модула argparse. Тук създадохме arg_parser, обект на ArgumentParser:

from argparse import ArgumentParser

arg_parser = ArgumentParser()

След това бихме искали да добавим два аргумента от командния ред:

  • съобщение: низът на съобщението и
  • файл: името на файла, с който искаме да работим.

Сега извикваме метода add_argument() на arg_parser, за да добавим и двата аргумента. В извикването на метода add_argument() можете да зададете помощ на низ (описание на аргумента).

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

Досега сме инстанциирали arg_parser и сме добавили аргументите на командния ред. Когато програмата се изпълнява от командния ред, можете да използвате метода parse_args() на arg_parser, за да получите стойностите на аргументите.

Тук улавяме пространството от имена на аргументи в променливата args. Така че можете да използвате args.argument_name, за да получите стойностите на аргументите.

След като получим стойностите на аргументите, записваме низа на съобщението с разменен регистър (използвайки метода на низ swapcase()) във файла.

args = arg_parser.parse_args()

message = args.message
file = args.file

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

Обединявайки всичко това, ето нашия файл 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())

Разбиране на използването на аргументи от командния ред

За да разберете използването на аргументите при стартиране на main.py, можете да използвате опцията –help long, както е показано:

$ 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

Няма незадължителни аргументи и както съобщението, така и файлът са задължителни позиционни аргументи. Като алтернатива можете също да използвате кратката опция -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

Както се вижда, и двата аргумента са позиционни по подразбиране. Така че, ако не подадете един или повече от тези аргументи, ще попаднете на грешки.

Тук сме предали позиционен аргумент (Hello) за низа на съобщението, но не сме предоставили никаква стойност за аргумента на файла.

И получаваме грешка, че се изисква файловият аргумент.

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

Когато стартираме main.py с двата позиционни аргумента, виждаме, че пространството от имена args съдържа стойностите на аргументите.

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

Сега, ако разгледаме съдържанието на текущата работна директория, виждаме, че скриптът създава файла ‘file1.txt’:

$ ls
file1.txt  main.py

Оригиналният низ на съобщението е ‘Hello’; след смяна на регистъра, низът на съобщението във файла ‘file1.txt’ е ‘hELLO’.

$ cat file1.txt
hELLO

Как да направите аргументите на командния ред незадължителни

За да направите тези аргументи на командния ред незадължителни, можете да поставите пред името на аргумента –.

  Как да излезете дистанционно от Netflix

Нека модифицираме 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')

Тъй като аргументите на командния ред са незадължителни, можем да зададем стойности по подразбиране за тези аргументи.

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

В този момент файлът 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)

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

Ако проверим употребата, виждаме, че и съобщението, и файлът са незадължителни аргументи. Което означава, че сега можете да стартирате main.py без тези два аргумента.

$ 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

В пространството на имената на аргументите файлът и съобщението са None.

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

Виждаме, че се използват името на файла и съобщението по подразбиране „myfile.txt“ и „Python3“. Файлът „myfile.txt“ вече е в работната директория:

$ ls
file1.txt  main.py  myfile.txt

И съдържа низа „Python3“ с разменени регистър на буквите:

$ cat myfile.txt
pYTHON3

Можете също така да използвате аргументите –message и –file, за да направите командата по-четлива.

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

Виждаме „file2.txt“ в работната директория:

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

И съдържа низа „CODING“, както се очаква.

$ cat file2.txt
cODING

Заключение

Ето обобщение на това, което научихме в този урок:

  • Подобно на езика за програмиране C, в Python можете да получите достъп до аргументите на командния ред, като преминете през вектора на аргументите sys.argv. sys.argv[0] е името на скрипта на Python. Така че ни интересува анализирането на аргументите sys.argv[1:].
  • Въпреки това, за да подобрите четливостта и да можете да добавяте опции, можете да използвате модулите getopt и argparse.
  • Можете да използвате модула getopt, за да анализирате списъка с аргументи на командния ред, започвайки от индекс 1 до края на списъка. Можете да посочите както къси опции, така и дълги опции.
  • Когато дадена опция приема аргумент, можете да посочите двоеточие (:) и = съответно след кратката опция и дългата опция.
  • С модула argparse на Python можете да създадете обект на ArgumentParser и да използвате метода add_argument(), за да добавите необходим позиционен аргумент. Използвайте — преди името на аргумента, за да го направите незадължителен.
  • За да извлечете стойностите на аргументите на командния ред, извикайте метода parse_args() на обекта ArgumentParser.

След това научете как да извършвате защитено хеширане в Python.