Рубрики
Без рубрики

Аргументы командной строки в Python

В этом уроке мы погружаемся в аргументы командной строки в Python. Используя модуль sys, модуль getopt и модуль argparse, мы будем анализировать и читать аргументы.

Автор оригинала: 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 , мы просто упомянули его. Этот модуль следует совершенно другому подходу и будет подробно объяснен в одной из следующих статей.

Рекомендации