Автор оригинала: Frank Hofmann.
Обзор
Поскольку Python является таким популярным языком программирования, а также имеет поддержку большинства операционных систем, он стал широко использоваться для создания инструментов командной строки для многих целей. Эти инструменты могут варьироваться от простых приложений CLI до более сложных, таких как AWS’ aws cli tool.
Сложные инструменты , подобные этому, обычно управляются пользователем с помощью аргументов командной строки , что позволяет пользователю использовать определенные команды, устанавливать параметры и многое другое. Например, эти параметры могут указывать инструменту выводить дополнительную информацию, считывать данные из указанного источника или отправлять выходные данные в определенное место.
Как правило, аргументы передаются инструментам CLI по-разному, в зависимости от вашей операционной системы:
- Unix-like:
-
за которым следует буква, например-h
, или--
за которой следует слово, например--help
- Windows:
/
за ним следует либо буква, либо слово, например/help
Эти различные подходы существуют в силу исторических причин. Многие программы в Unix-подобных системах поддерживают как одинарную, так и двойную тире-нотацию. Одинарная тире-нотация в основном используется с однобуквенными опциями, в то время как двойные тире представляют собой более читаемый список опций, что особенно полезно для сложных опций, которые должны быть более явными.
Примечание : В этой статье мы сосредоточимся исключительно на Unix-подобном формате -
и --
.
Имейте в виду, что и имя, и значение аргумента специфичны для программы – нет никакого общего определения, кроме нескольких общих соглашений, таких как --help
для получения дополнительной информации об использовании инструмента. Как разработчик скрипта Python, вы будете решать, какие аргументы предоставить вызывающему и что они делают. Это требует надлежащей оценки.
По мере того, как список доступных аргументов будет расти, ваш код будет усложняться в попытке точно проанализировать их. К счастью, в Python есть несколько доступных библиотек, которые помогут вам в этом. Мы рассмотрим несколько наиболее распространенных решений, которые варьируются от “сделай сам” с помощью sys.argv
до подхода “сделано для тебя” с помощью argparse
.
Обработка аргументов командной строки с помощью Python
Python 3 поддерживает несколько различных способов обработки аргументов командной строки. Встроенный способ заключается в использовании модуля sys
. Что касается имен и их использования, то они напрямую связаны с библиотекой C ( libc
). Второй способ-это модуль getopt
, который обрабатывает как короткие, так и длинные параметры, включая оценку значений параметров.
Кроме того, существуют два других распространенных метода. Это модуль argparse , который является производным от модуля optparse
, доступного до Python 2.7. Другой метод использует модуль docopt
, который доступен на GitHub .
Каждый из этих способов имеет свои плюсы и минусы, поэтому стоит оценить каждый из них, чтобы увидеть, какой из них лучше всего соответствует вашим потребностям.
Модуль sys
Это базовый модуль, который поставляется вместе с Python с самого начала. Он использует очень похожий подход к библиотеке C, используя argc
//argv для доступа к аргументам. Модуль
sys реализует аргументы командной строки в простой структуре списка с именем sys.argv .
Каждый элемент списка представляет один аргумент. Первый элемент в списке, sys.argv[0]
, – это имя скрипта Python. Остальные элементы списка, sys.argv[1]
to sys.argv[n]
, являются аргументами командной строки от 2 до n. В качестве разделителя между аргументами используется пробел. Значения аргументов, содержащие в нем пробел, должны быть заключены в кавычки, чтобы быть правильно проанализированными с помощью sys
.
Эквивалент argc
– это просто количество элементов в списке. Чтобы получить это значение, используйте оператор Python len ()
. Позже мы покажем это в примере кода.
Печать первого аргумента CLI
В этом первом примере наш скрипт определит способ его вызова. Эта информация хранится в первом аргументе командной строки, индексируемом с 0. Приведенный ниже код показывает, как вы получаете имя вашего скрипта Python.
import sys print ("The script has the name %s" % (sys.argv[0])
Сохраните этот код в файле с именем arguments-program-name.py, а затем назовите его, как показано ниже. Выходные данные выглядят следующим образом и содержат имя файла, включая его полный путь:
$ python arguments-program-name.py The script has the name arguments-program-name.py $ python /home/user/arguments-program-name.py The script has the name /home/user/arguments-program-name.py
Как вы можете видеть из второго вызова выше, мы получаем не только имя файла Python, но и полный путь, используемый для его вызова.
Подсчет количества аргументов
Во втором примере мы просто подсчитываем количество аргументов командной строки с помощью встроенного метода len ()
. sys.argv
– это список, который мы должны изучить. В приведенном ниже коде мы получаем количество аргументов, а затем вычитаем 1, потому что один из этих аргументов (то есть первый) всегда задается как имя файла, что не всегда полезно для нас. Таким образом, фактическое количество аргументов, переданных пользователем, равно len(sys.argv) - 1
.
import sys # Count the arguments arguments = len(sys.argv) - 1 print ("The script is called with %i arguments" % (arguments))
Сохраните и назовите этот файл arguments-count.py. Некоторые примеры вызова этого скрипта приведены ниже. Это включает в себя три различных сценария:
- Вызов без каких-либо дополнительных аргументов командной строки
- Вызов с двумя аргументами
- Вызов с двумя аргументами, где второй-это строка в кавычках, содержащая пробел
$ python arguments-count.py The script is called with 0 arguments $ python arguments-count.py --help me The script is called with 2 arguments $ python arguments-count.py --option "long string" The script is called with 2 arguments
Перебор Аргументов
Наш третий пример выводит каждый аргумент, отправленный скрипту Python, за исключением самого имени программы. Поэтому мы перебираем аргументы командной строки, начиная с элемента second list. Напомним, что это индекс 1, так как списки в Python основаны на 0.
import sys # Count the arguments arguments = len(sys.argv) - 1 # Output argument-wise position = 1 while (arguments >= position): print ("Parameter %i: %s" % (position, sys.argv[position])) position = position + 1
Ниже мы называем наш код, который был сохранен в файл arguments-output.py. Как и в нашем предыдущем примере, выходные данные иллюстрируют три различных вызова:
- Вызов без всяких аргументов
- Вызов с двумя аргументами
- Вызов с двумя аргументами, где второй аргумент представляет собой строку в кавычках, содержащую пробел
$ python arguments-output.py $ python arguments-output.py --help me Parameter 1: --help Parameter 2: me $ python arguments-output.py --option "long string" Parameter 1: --option Parameter 2: long string
Помните, что смысл показа примера строки в кавычках заключается в том, что параметры обычно разделяются пробелом, если только они не окружены кавычками.
Модуль getopt
Как вы, возможно, уже заметили, модуль sys
разбивает строку командной строки только на отдельные грани. Модуль Python getopt идет немного дальше и расширяет разделение входной строки проверкой параметров. Основываясь на функции getopt
C, он допускает как короткие, так и длинные варианты, включая присвоение значения.
На практике для правильной обработки входных данных требуется модуль sys
. Для этого необходимо предварительно загрузить как модуль sys
, так и модуль getopt
. Далее из списка входных параметров мы удаляем первый элемент списка (см. код ниже), а оставшийся список аргументов командной строки сохраняем в переменной с именем argument_list
.
# Include standard modules import getopt, sys # Get full command-line arguments full_cmd_arguments = sys.argv # Keep all but the first argument_list = full_cmd_arguments[1:] print argument_list
Аргументы в argument_list
теперь можно анализировать с помощью метода getopts ()
. Но прежде чем это сделать, нам нужно сообщить getopts()
о том, какие параметры являются допустимыми. Они определяются следующим образом:
short_options = "ho:v" long_options = ["help", "output=", "verbose"]
Это означает, что эти аргументы являются теми, которые мы считаем действительными, наряду с некоторой дополнительной информацией:
------------------------------------------ long argument short argument with value ------------------------------------------ --help -h no --output -o yes --verbose -v no ------------------------------------------
Возможно, вы заметили, что вариант o
short был продолжен двоеточием, :
. Это говорит getopt
о том, что этому параметру должно быть присвоено значение.
Теперь это позволяет нам обработать список аргументов. Метод getopt()
требует настройки трех параметров – списка фактических аргументов из argv
, а также допустимых коротких и длинных параметров (показано в предыдущем фрагменте кода).
Сам вызов метода хранится в операторе try-catch для покрытия ошибок во время вычисления. Исключение возникает, если обнаружен аргумент, который не является частью списка, как было определено ранее. Скрипт Python выведет сообщение об ошибке на экран и завершит работу с кодом ошибки 2.
try: arguments, values = getopt.getopt(argument_list, short_options, long_options) except getopt.error as err: # Output error, and return with an error code print (str(err)) sys.exit(2)
Наконец, аргументы с соответствующими значениями хранятся в двух переменных с именами arguments
и values
. Теперь вы можете легко оценить эти переменные в своем коде. Мы можем использовать for
-цикл для перебора списка распознанных аргументов, одну запись за другой.
# Evaluate given options for current_argument, current_value in arguments: if current_argument in ("-v", "--verbose"): print ("Enabling verbose mode") elif current_argument in ("-h", "--help"): print ("Displaying help") elif current_argument in ("-o", "--output"): print (("Enabling special output mode (%s)") % (current_value))
Ниже вы можете увидеть результаты выполнения этого кода. Мы покажем, как программа реагирует как с допустимыми, так и с недопустимыми аргументами программы:
$ python arguments-getopt.py -h Displaying help $ python arguments-getopt.py --help Displaying help $ python arguments-getopt.py --output=green --help -v Enabling special output mode (green) Displaying help Enabling verbose mode $ python arguments-getopt.py -verbose option -e not recognized
Последний звонок в нашу программу поначалу может показаться немного запутанным. Чтобы понять это, вам нужно знать, что варианты стенографии (иногда также называемые флагами) могут использоваться вместе с одним тире. Это позволяет вашему инструменту легче принимать множество вариантов. Например, вызов python arguments-getopt.py -vh
– это то же самое, что вызов python arguments-getopt.py -в -ч
. Таким образом, в последнем вызове выше модуль getopt
думал, что пользователь пытается передать -e
в качестве опции, что является недопустимым.
Модуль argparse
Модуль argparse был доступен с Python 3.2, а также усовершенствование модуля optparse
, который существует до Python 2.7. Документация Python содержит описание API и учебник, который подробно описывает все методы.
Модуль предлагает интерфейс командной строки со стандартизированным выводом, в то время как первые два решения оставляют большую часть работы в ваших руках. argparse
позволяет проверять фиксированные и необязательные аргументы с проверкой имени как в коротком, так и в длинном стиле. В качестве необязательного аргумента по умолчанию он включает в себя -h
, а также его длинную версию --help
. Этот аргумент сопровождается справочным сообщением по умолчанию, описывающим принятые аргументы.
В приведенном ниже коде показана инициализация парсера, а в приведенном ниже выводе-базовый вызов, за которым следует справочное сообщение. В отличие от вызовов Python, которые мы использовали в предыдущих примерах, имейте в виду использовать Python 3 с этими примерами.
# Include standard modules import argparse # Initiate the parser parser = argparse.ArgumentParser() parser.parse_args()
$ python3 arguments-argparse-basic.py $ python3 arguments-argparse-basic.py -h usage: arguments-argparse-basic.py [-h] optional arguments: -h, --help show this help message and exit $ python3 arguments-argparse-basic.py --verbose usage: arguments-argparse-basic.py [-h] arguments-argparse-basic.py: error: unrecognized arguments: --verbose
На следующем шаге мы добавим пользовательское описание в справочное сообщение для наших пользователей. Инициализация парсера таким образом позволяет получить дополнительный текст. Приведенный ниже код хранит описание в переменной text
, которая явно задается классу argparse
в качестве параметра description
. Вызывая этот код ниже, вы можете увидеть, как выглядит вывод.
# Include standard modules import argparse # Define the program description text = 'This is a test program. It demonstrates how to use the argparse module with a program description.' # Initiate the parser with a description parser = argparse.ArgumentParser(description=text) parser.parse_args()
$ python3 arguments-argparse-description.py --help usage: arguments-argparse-description.py [-h] This is a test program. It demonstrates how to use the argparse module with a program description. optional arguments: -h, --help show this help message and exit
В качестве последнего шага мы добавим необязательный аргумент с именем -V
, который имеет соответствующий длинный аргумент стиля с именем --version
. Для этого мы используем метод add_argument ()
, который вызываем с тремя параметрами (отображается только для --version
):
- Имя параметра:
--version
- Текст справки для параметра:
help="показать версию программы"
- Action (без дополнительного значения):
action="store_true"
Исходный код для этого показан ниже. Чтение аргументов в переменную с именем args
выполняется с помощью метода parse_args()
из объекта parser
. Обратите внимание, что вы отправляете как короткую, так и длинную версию в одном вызове. Наконец, вы проверяете, есть ли атрибуты args.V
или args.version
устанавливаются и выводят сообщение version.
# Include standard modules import argparse # Initiate the parser parser = argparse.ArgumentParser() parser.add_argument("-V", "--version", help="show program version", action="store_true") # Read arguments from the command line args = parser.parse_args() # Check for --version or -V if args.version: print("This is myprogram version 0.1")
$ python3 arguments-argparse-optional.py -V This is myprogram version 0.1 $ python3 arguments-argparse-optional.py --version This is myprogram version 0.1
Аргумент --version
не требует указания значения в командной строке. Вот почему мы устанавливаем аргумент action в "store_true"
. В других случаях вам может потребоваться дополнительное присвоенное значение, например, если вы задаете определенный объем, высоту или ширину. Это показано в следующем примере. В случае по умолчанию обратите внимание, что все аргументы интерпретируются как строки.
# Include standard modules import argparse # Initiate the parser parser = argparse.ArgumentParser() # Add long and short argument parser.add_argument("--width", "-w", help="set output width") # Read arguments from the command line args = parser.parse_args() # Check for --width if args.width: print("Set output width to %s" % args.width)
Здесь мы покажем, что происходит при подаче различных значений аргументов. Это включает в себя как короткую, так и длинную версию, а также справочное сообщение.
$ python3 arguments-argparse-optional2.py -w 10 Set output width to 10 $ python3 arguments-argparse-optional2.py --width 10 Set output width to 10 $ python3 arguments-argparse-optional2.py -h usage: arguments-argparse-optional2.py [-h] [--width WIDTH] optional arguments: -h, --help show this help message and exit --width WIDTH, -w WIDTH set output width
Вывод
В этой статье мы показали множество различных методов извлечения аргументов командной строки в Python, включая использование sys
, getopt
и argparse
. Эти модули различаются по функциональности, некоторые обеспечивают гораздо больше, чем другие. sys
полностью гибок, в то время как getopt
и argparse
требуют некоторой структуры. Напротив, они охватывают большую часть сложной работы, которую sys
оставляет на ваше усмотрение. После работы с приведенными примерами вы сможете определить, какой модуль лучше всего подходит для вашего проекта.
В этой статье мы не говорили о других решениях, таких как модуль docopts
, мы просто упомянули его. Этот модуль следует совершенно другому подходу и будет подробно объяснен в одной из следующих статей.