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

Сегодня разберемся с сабпарсерами объекта argparse.ArgumentParser, которые передаются через параметр parents.

В общем случае при попытке распарсить аргументы командной строки мы создаем объект и начинаем методично добавлять к нему все известные нам параметры.

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

При этом мы можем управлять тем, какие аргументы будут парсится.

Для этого в параметры parents можно передать те объекты, от которых надо унаследоваться.

Рассмотрим на примерах.

В первом случае создается ArgumentParser с одним аргументом. И он сразу же разбирает командную строку на известные параметры и хвост при помощи parse_known_args.

В зависимости от значения -l мы либо продолжим работу, либо остановимся.

import argparse  
  
parser = argparse.ArgumentParser(add_help=False)  
parser.add_argument('-l', '--list', help="List something", action='store_true')  
args, remaining = parser.parse_known_args()  
  
if args.list:  
   print('List')  
   exit(0)  
  
parser = argparse.ArgumentParser(  
   description="Chained parsers",  
   formatter_class=argparse.RawDescriptionHelpFormatter,  
   parents=[parser])  
  
parser.add_argument('-t', '--test', help="Test", action='store_true')  
other_args = parser.parse_args(remaining)  
  
print('Args: {}'.format(other_args))

Второй пример чуть более сложный.

Допустим, что код обрабатывает видеофайлы и аудиофайлы. В зависимости от этого у него меняется поведение атрибута -r.

import argparse  
import enum  
  
class Formats(enum.Enum):  
   VIDEO='video'  
   AUDIO='audio'  
  
   def __str__(self):  
       return self.value  
  
def parser_common():  
   parser = argparse.ArgumentParser(add_help=False)  
   parser.add_argument(  
       '-f', '--format', help="Specify format", type=Formats, choices=list(Formats)  
   )  
   return parser  
  
def parser_video(parent_parser: argparse.ArgumentParser) -> argparse.ArgumentParser:  
   parser = argparse.ArgumentParser(  
       description="Video parser",  
       formatter_class=argparse.RawDescriptionHelpFormatter,  
       parents=[parent_parser])  
   parser.add_argument(  
       '-r',  
       '--resolution',  
       help="Resolution",  
       type=int,  
       nargs=2,  
       metavar=('WIDTH', 'HEIGHT'),  
       required=True,  
   )  
   return parser  
  
def parser_audio(parent_parser: argparse.ArgumentParser) -> argparse.ArgumentParser:  
   parser = argparse.ArgumentParser(  
       description="Audio parser",  
       formatter_class=argparse.RawDescriptionHelpFormatter,  
       parents=[parent_parser])  
   parser.add_argument(  
       '-r',  
       '--resolution',  
       help="Audit resolution",  
       type=int,  
       required=True,  
   )  
   return parser  
  
def main():  
   parser = parser_common()  
   args, remaining = parser.parse_known_args()  
   if args.format == Formats.AUDIO:  
       parser = parser_audio(parser)  
   elif args.format == Formats.VIDEO:  
       parser = parser_video(parser)  
   else:  
       parser.print_help()  
       exit(1)  
  
   other_args = parser.parse_args(remaining)  
   print(2)  
   print('Args: {}'.format(other_args))  
  
if __name__ == '__main__':  
   main()

Запустите и посмотрите, как ведёт себя данный код.

$ python argsparser.py
usage: argsparser.py [-f {video,audio}]

options:
  -f {video,audio}, --format {video,audio}
                        Specify format
$ python argsparser.py -f audio
usage: argsparser.py [-h] [-f {video,audio}] -r RESOLUTION
argsparser.py: error: the following arguments are required: -r/--resolution
$ python argsparser.py -f video
usage: argsparser.py [-h] [-f {video,audio}] -r WIDTH HEIGHT
argsparser.py: error: the following arguments are required: -r/--resolution
$ python argsparser.py -f video -h
usage: argsparser.py [-h] [-f {video,audio}] -r WIDTH HEIGHT

Video parser

options:
  -h, --help            show this help message and exit
  -f {video,audio}, --format {video,audio}
                        Specify format
  -r WIDTH HEIGHT, --resolution WIDTH HEIGHT
                        Resolution
$ python argsparser.py -f audio -h
usage: argsparser.py [-h] [-f {video,audio}] -r RESOLUTION

Audio parser

options:
  -h, --help            show this help message and exit
  -f {video,audio}, --format {video,audio}
                        Specify format
  -r RESOLUTION, --resolution RESOLUTION
                        Audit resolution

Категории: HowTo