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

Обзор

Поскольку Python является очень популярным языком программирования, а также поддерживает большинство операционных систем и множество библиотек, упрощающих обработку аргументов командной строки, он стал широко использоваться для создания инструментов командной строки для многих целей. Эти инструменты могут варьироваться от простых приложений CLI до более сложных, таких как AWS. авскли инструмент.

Подобные сложные инструменты обычно контролируются пользователем через аргументы командной строки, который позволяет пользователю использовать определенные команды, устанавливать параметры и многое другое. Например, эти параметры могут указывать инструменту выводить дополнительную информацию, читать данные из указанного источника или отправлять выходные данные в определенное место.

В общем, аргументы передаются инструментам CLI по-разному, в зависимости от вашей операционной системы:

  • Unix-подобный: - за которым следует буква, например -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, также обеспечивает ту же функциональность.

В последнее время absl библиотека также набирает обороты как средство замены optparse и getopt().

У каждого из этих способов есть свои плюсы и минусы, поэтому стоит оценить каждый из них, чтобы понять, какой из них лучше всего соответствует вашим потребностям.

Системный модуль

Это базовый модуль, поставляемый вместе с Python с самого начала. Подход очень похож на библиотеку C, используя argc/argv чтобы получить доступ к аргументам. системный модуль реализует аргументы командной строки в простой структуре списка с именем sys.argv.

Каждый элемент списка представляет один аргумент. Первый элемент в списке, sys.argv[0], — это имя скрипта Python. Остальные элементы списка, sys.argv[1] в 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


arguments = len(sys.argv) - 1
print ("The script is called with %i 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, за исключением самого имени программы. Поэтому мы просматриваем аргументы командной строки, начиная с второй элемент списка. Напомним, что это индекс 1, поскольку в Python списки отсчитываются от 0:

import sys


arguments = len(sys.argv) - 1


position = 1
while (arguments >= position):
    print ("Parameter %i: %s" % (position, sys.argv[position]))
    position = position + 1

Ниже мы вызываем наш код, который был сохранен в файле аргументы-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

Помните, что смысл примера строки в кавычках заключается в том, что параметры обычно разделяются пробелом. если не они заключены в кавычки.

Флаги спуска (absl)

Библиотека флагов Abseil предназначена для переноса аргументов командной строки в производство с помощью распределенных аргументов командной строки. Когда модуль использует флаги командной строки и импортируется в другой модуль – другой модуль также импортирует флагии может обрабатывать их, пересылая в импортированный модуль.

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

Кроме того, библиотека позволяет вам определять значения по умолчанию, описания и типы данных аргументов, поэтому дополнительные проверки и преобразования не требуются.

from absl import flags
import sys


flags.DEFINE_string('name', 'User', 'The name of the user.')


FLAGS = flags.FLAGS
FLAGS(sys.argv)

print(f"Hello {FLAGS.name}!")

Поддерживаемые типы данных:

  • DEFINE_integer()
  • DEFINE_string()
  • DEFINE_bool()
  • DEFINE_enum()
  • DEFINE_list()
  • DEFINE_float()

А также DEFINE_multi_integer(), DEFINE_multi_string() и DEFINE_multi_enum() для ввода нескольких аргументов. Кроме того, бег --help, --helpfullи т. д. распечатайте существующие флаги и их описания в разных форматах.

Ознакомьтесь с нашим практическим руководством по изучению Git с рекомендациями, принятыми в отрасли стандартами и прилагаемой памяткой. Перестаньте гуглить команды Git и на самом деле изучить это!

Библиотека также позволяет определять проверки — как с точки зрения диапазона, например, целочисленные значения, имеющие upper_bound or lower_bound это приемлемо, и запуск произвольных методов для проверки значений:

def validate_name(value):
    return len(value) > 15

flags.register_validator('name',
                         validate_name,
                         message='Name is over 15 characters long.',
                         flag_values=FLAGS)

Собираем их в конкретный пример:

from absl import flags
import sys

flags.DEFINE_string('name', 'User', 'The name of the user.')
flags.DEFINE_integer('tasks', 0, 'The number of tasks a user has.', lower_bound=0)

FLAGS = flags.FLAGS
FLAGS(sys.argv)

print(f"{FLAGS.name} has {FLAGS.tasks} tasks to work on.")
$ python flags.py --name=John --tasks=5
John has 5 tasks to work on.
$ python flags.py --name=John --tasks=-1

Traceback (most recent call last):
  File "/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/site-packages/absl/flags/_flag.py", line 180, in _parse
    return self.parser.parse(argument)
  File "/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/site-packages/absl/flags/_argument_parser.py", line 168, in parse
    raise ValueError('%s is not %s' % (val, self.syntactic_help))
ValueError: -1 is not a non-negative integer
...

Модуль argparse

Ассоциация модуль argparse доступен начиная с Python 3.2, а также является усовершенствованием optparse модуль, существующий до Python 2.7. Документация Python содержит описание API и руководство, в котором подробно описаны все методы.

Модуль предлагает интерфейс командной строки со стандартизированным выводом, тогда как первые два решения оставляют большую часть работы в ваших руках. argparse позволяет проверять фиксированные и необязательные аргументы с проверкой имени как в коротком, так и в длинном стиле. В качестве необязательного аргумента по умолчанию он включает -h, вместе с его длинной версией --help. Этот аргумент сопровождается справочным сообщением по умолчанию, описывающим принятые аргументы.

Код ниже показывает инициализацию синтаксического анализатора, а выходные данные ниже, показывающие базовый вызов, за которым следует справочное сообщение. В отличие от вызовов Python, которые мы использовали в предыдущих примерах, не забывайте использовать Python 3 в этих примерах:


import argparse


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 параметр. Вызвав этот код ниже, вы можете увидеть, как выглядит результат:


import argparse


text = 'This is a test program. It demonstrates how to use the argparse module with a program 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="show program version"
  • Действие (без дополнительной стоимости): action="store_true"

Исходный код для этого показан ниже. Чтение аргументов в переменную с именем args делается через parse_args() метод из parser объект. Обратите внимание, что вы отправляете как короткую, так и полную версию за один вызов. Наконец, вы проверяете, являются ли атрибуты args.V or args.version установлены и выводят сообщение о версии:


import argparse


parser = argparse.ArgumentParser()
parser.add_argument("-V", "--version", help="show program version", action="store_true")


args = parser.parse_args()


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


import argparse


parser = argparse.ArgumentParser()


parser.add_argument("--width", "-w", help="set output width")


args = parser.parse_args()


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

Модуль getopt

Как вы, возможно, уже заметили, sys Модуль разбивает строку командной строки только на отдельные фасеты. Питон модуль getopt идет немного дальше и расширяет разделение входной строки путем проверки параметров. На основе getopt C, она допускает как короткие, так и длинные варианты, включая присвоение значения.

На практике это требует sys модуль для правильной обработки входных данных. Для этого оба sys модуль и getopt модуль необходимо загрузить заранее. Далее из списка входных параметров мы удаляем первый элемент списка (см. код ниже) и сохраняем оставшийся список аргументов командной строки в переменной с именем argument_list:


import getopt, sys


full_cmd_arguments = sys.argv


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 короткий вариант начинался через двоеточие, :, Это говорит getopt что этой опции должно быть присвоено значение.

Теперь это позволяет нам обрабатывать список аргументов. getopt() метод требует настройки трёх параметров — списка фактических аргументов из argv, а также допустимые короткие и длинные параметры (показаны в предыдущем фрагменте кода).

Сам вызов метода сохраняется в операторе try-catch, чтобы исключить ошибки во время оценки. Исключение возникает, если обнаружен аргумент, который не является частью списка, определенного ранее. Сценарий Python выведет сообщение об ошибке на экран и завершит работу с кодом ошибки 2:

try:
    arguments, values = getopt.getopt(argument_list, short_options, long_options)
except getopt.error as err:
    
    print (str(err))
    sys.exit(2)

Наконец, аргументы с соответствующими значениями сохраняются в двух переменных с именами arguments и values. Теперь вы можете легко оценить эти переменные в своем коде. Мы можем использовать for-цикл для перебора списка распознанных аргументов, одна запись за другой.


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 -v -h. Итак, в последнем вызове выше getopt модуль думал, что пользователь пытается пройти -e как вариант, который недействителен.

Заключение

В этой статье мы показали множество различных методов получения аргументов командной строки в Python, в том числе использование sys, getoptи argparse. Эти модули различаются по функциональности, некоторые предоставляют гораздо больше, чем другие. sys является полностью гибким, тогда как оба getoptи argparse требуют некоторой структуры. Напротив, они охватывают большую часть сложной работы, sys оставляет на ваше усмотрение. Проработав предоставленные примеры, вы сможете определить, какой модуль лучше всего подходит для вашего проекта.

В этой статье мы не говорили о других решениях, таких как docopts модуль, мы только что упомянули об этом. Этот модуль использует совершенно другой подход и будет подробно описан в одной из следующих статей.

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

Отметка времени:

Больше от Стекабьюс