Если вы занимаетесь обработкой и анализом данных с использованием Python, то вам, рано или поздно, придётся выйти за пределы Jupyter Notebook, преобразовав свой код в скрипты, которые можно запускать средствами командной строки. Здесь вам и пригодится модуль argparse. Для новичков, привыкших к Jupyter Notebook, такой шаг означает необходимость покинуть зону комфорта и перейти в новую среду. Материал, перевод которого мы публикуем сегодня, написан для того, чтобы облегчить подобный переход.
Модуль argparse
Модуль argparse
Модуль argparse можно сравнить с силами природы, которые воздвигли горные пики, возвышающиеся над облаками. Благодаря этому модулю в скриптах становится возможным работа с тем, что, без его использования, было бы скрыто от кода этих скриптов.
Надо отметить, что argparse является рекомендуемым к использованию модулем стандартной библиотеки Python, предназначенным для работы с аргументами командной строки. Мне не удалось найти хорошее руководство по argparse для начинающих, поэтому я и решил написать такое руководство сам.
Жизнь за пределами Jupyter Notebook
Когда я впервые столкнулся с argparse в Python-скрипте, который нужен был мне для проекта, которым я занимался в свободное время, я подумал: «А это что ещё за таинственная конструкция?». После этого я быстро перенёс код в Jupyter Notebook, но такой ход оказался нерациональным.
Мне нужно было, чтобы у меня была возможность просто запустить скрипт, а не работать с ним средствами Jupyter Notebook. Автономным скриптом, в котором использовался модуль argparse, было бы гораздо легче пользоваться, работать над ним было бы проще, чем полагаясь на возможности Jupyter Notebook. Однако тогда я спешил, и, когда взглянул на документацию по argparse, не смог сходу ухватить её суть, поэтому и не стал пользоваться исходной версией скрипта.
С тех пор я разобрался с argparse и этот модуль мне очень понравился. Теперь я считаю его прямо-таки жизненно необходимым. При этом освоить его не так уж и сложно.
Зачем нужен модуль argparse?
Модуль argparse позволяет разбирать аргументы, передаваемые скрипту при его запуске из командной строки, и даёт возможность пользоваться этими аргументами в скрипте. То есть речь идёт о том, что этот модуль позволяет предоставлять скрипту некие данные в момент его запуска, а этими данными скрипт сможет воспользоваться во время выполнения его кода. Модуль argparse — это средство, с помощью которого можно наладить общение между автором программы и тем, кто ей пользуется, например — между вами, когда вы сегодня пишете скрипт, и вами же, когда вы завтра его запускаете, что-то ему передавая.
Использование argparse означает, что, при необходимости изменить поведение скрипта или при необходимости передачи ему неких данных, если это предусмотрено автором скрипта, пользователю не нужно редактировать программный код. В результате скрипты обретают определённый уровень гибкости.
Пример
Предположим, вы хотите написать скрипт для преобразования видеофайлов в обычные изображения с использованием библиотеки OpenCV. Для того чтобы скрипт мог бы решить эту задачу, ему нужно знать место, где хранятся видеофайлы, и место, в которое нужно поместить готовые изображения. То есть, ему требуются сведения о двух папках, пути к которым, что не очень удобно, можно жёстко задать в коде скрипта, или, что уже куда лучше, можно позволить задавать пользователю скрипта, вводя их в качестве аргументов командной строки при запуске скрипта. Для того чтобы оснастить скрипт такой возможностью, нам и пригодится модуль argparse. Вот как может выглядеть раздел скрипта (назовём этот скрипт videos.py
), в котором осуществляется разбор аргументов командной строки:
# videos.py
import argparse
parser = argparse.ArgumentParser(description='Videos to images')
parser.add_argument('indir', type=str, help='Input dir for videos')
parser.add_argument('outdir', type=str, help='Output dir for image')
args = parser.parse_args()
print(args.indir)
Здесь, в начале файла, импортируется модуль argparse. Затем, с использованием конструкции argparse.ArgumentParser()
, создаётся объект parser
с указанием его описания. Далее, с помощью метода parser.add_argument()
, описывается переменная indir
, в которую планируется записать путь к папке с видеофайлами. При этом указывается то, что она имеет строковой тип, а также задаётся справочная информация о ней. После этого, точно так же, создаётся переменная outdir
, в которую попадёт путь к папке, в которую скрипт должен будет поместить изображения, созданные на основе видеофайлов. На следующем шаге работы в переменную args
попадает результат разбора аргументов командной строки. То, что передано скрипту при запуске, теперь будет доступно в виде свойств indir
и outdir
объекта args
. Теперь с этими значениями можно работать. В данном случае мы просто выводим в консоль то, что передано скрипту в аргументе indir
.
Вот как запустить этот скрипт из командной строки:
python videos.py /videos /images
Обратите внимание на то, что строки /videos
и /images
не нужно заключать в кавычки. Скрипт, запущенный таким образом, выведет в терминал строку /videos
, чем подтвердит возможность использования переданных ему аргументов в своём коде. Это — магия argparse в действии.
Магия разбора аргументов командной строки
Подробности об argparse
Только что мы рассмотрели простой пример работы с argparse. Теперь давайте обсудим некоторые подробности, касающиеся argparse.
▍Позиционные аргументы
Конструкция вида parser.add_argument('indir', type=str, help='Input dir for videos')
из скрипта videos.py
предназначена для создания позиционного аргумента (positional argument). При вызове скрипта важен порядок указания таких аргументов. Так, первый аргумент, переданный скрипту, становится первым позиционным аргументом, второй аргумент — вторым позиционным аргументом.
Что произойдёт в том случае, если скрипт запустить вообще без аргументов, выполнив в терминале команду python videos.py
?
В таком случае будет выведено сообщение об ошибке следующего вида:
videos.py: error: the following arguments are required: indir, outdir
В результате оказывается, что для того, чтобы запустить скрипт, в котором предусмотрено использование позиционных аргументов, такие аргументы всегда нужно указывать при его запуске.
▍Необязательные аргументы
Что произойдёт при запуске нашего скрипта командой python videos.py --help
?
В ответ будет выведена справочная информация о нём. Это — именно те сведения о позиционных аргументах, которые мы указывали при описании соответствующих переменных:
usage: videos.py [-h] indir outdir
Videos to images
positional arguments:
indir Input dir for videos
outdir Output dir for image
optional arguments:
-h, --help show this help message and exit
Скрипт сообщил нам много интересного о том, чего он ждёт от пользователя, а help
— это пример необязательного аргумента (optional argument). Обратите внимание на то, что --help
(или -h
) — это единственный стандартный необязательный аргумент, которым мы можем пользоваться при работе с argparse, но, если вам нужны и другие необязательные аргументы, их можно создавать и самостоятельно.
Необязательные аргументы создают так же, как и позиционные. Основная разница между командами их создания заключается в том, что при указании имён таких аргументов эти имена начинаются с последовательности символов --
, или, для кратких форм аргументов, с символа -
. Например, необязательный аргумент можно создать так:
parser.add_argument('-m', '--my_optional')
Вот пример того, как создавать и использовать необязательные аргументы. Обратите внимание на то, что мы, описывая здесь необязательный аргумент, указали его тип как int
. То есть он представляет собой целое число. В подобной ситуации можно использовать и другие типы Python.
# my_example.py
import argparse
parser = argparse.ArgumentParser(description='My example explanation')
parser.add_argument(
'--my_optional',
type=int,
default=2,
help='provide an integer (default: 2)'
)
my_namespace = parser.parse_args()
print(my_namespace.my_optional)
Аргумент, описанный как --my_optional
, доступен в программе в виде свойства объекта my_namespace
с именем my_optional
.
Необязательным аргументам можно назначать значения, которые они будут иметь по умолчанию. В нашем случае, если при вызове скрипта аргументу my_example
не будет задано никакого значения, в него будет записано число 2, которое и будет выведено в консоль. Для того чтобы задать значение этого аргумента во время запуска скрипта можно воспользоваться такой конструкцией:
python my_example.py --my_optional=3
Для чего ещё можно использовать argparse?
Модуль argparse можно использовать при разработке Python-приложений, которые планируется упаковывать в контейнеры Docker. Так, например, если при запуске приложения, упакованного в контейнер, ему нужно передать аргументы командной строки, то описать это, на этапе сборки контейнера, можно в Dockerfile с помощью инструкции RUN
. Для запуска скриптов во время выполнения контейнера можно пользоваться инструкциями CMD
или ENTRYPOINT
. Подробности о файлах Dockerfile вы можете найти здесь.
Итоги
Мы рассмотрели базовые способы работы с модулем argparse, используя которые, вы можете оснастить свои скрипты возможностью принимать и обрабатывать аргументы командной строки. При этом надо отметить, что возможности argparse на этом не заканчиваются. Например, использование при описании аргументов параметра nargs позволяет работать со списками аргументов, а параметр choices позволяет задавать наборы значений, которые могут принимать аргументы. На самом деле, теперь, освоив основные возможности argparse, вы, без особых сложностей, сможете изучить этот модуль более глубоко, используя документацию к нему.
Если вы привыкли работать с Jupyter Notebook и хотите отойти от этой практики, то вот и вот — материалы по работе с переменными окружениями. Вот материал, посвящённый средству, repo2docker, позволяющему преобразовывать репозитории Jupyter Notebook в образы Docker.
Уважаемые читатели! Как вы работаете с аргументами командной строки в Python-скриптах?
Автор: ru_vds