Полное руководство по обработке аргументов командной строки в Python

Раздел: Системное программирование -> Взаимодействие с ОС

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

Как реализовать гибкий и документированный парсинг с поддержкой типов и помощи?

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

import argparse

parser = argparse.ArgumentParser(description='Обработка лог-файлов')
parser.add_argument('logfile', help='Путь к файлу журнала')
parser.add_argument('-o', '--output', default='output.txt', help='Файл для результата (по умолчанию output.txt)')
parser.add_argument('-v', '--verbose', action='store_true', help='Подробный вывод')
args = parser.parse_args()

print(f'Обрабатывается: {args.logfile}')
print(f'Результат будет сохранён в: {args.output}')
if args.verbose:
    print('Режим подробного вывода включён')

Python run exe file (запуск exe-файла из python)

Пояснение шагов: ArgumentParser создаёт парсер, add_argument описывает каждый параметр. Флаг action='store_true' делает опцию булевой. Метод parse_args() возвращает объект с атрибутами, соответствующими именам аргументов.

Типичная ошибка - указание несуществующей опции. Парсер автоматически выводит сообщение об ошибке и прекращает работу. Для избегания путаницы с типами добавляют параметр type=int или choices.

Как получить сырой список аргументов без какого-либо парсинга?

Самый простой способ - обратиться к атрибуту sys.argv. Это список строк, где первый элемент - имя скрипта, остальные - переданные аргументы. Подходит для быстрых прототипов или скриптов с одним-двумя позиционными параметрами.

import sys
print('Имя скрипта:', sys.argv[0])
print('Аргументы:', sys.argv[1:])
if len(sys.argv) > 2:
    print('Второй аргумент:', sys.argv[2])

Python send files (отправка файлов в python)

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

Проблема: отсутствие проверки типов, документации, поддержки опций. При изменении порядка аргументов легко допустить ошибку. Решение - переходить на argparse при усложнении интерфейса.

Как обработать короткие и длинные опции в стиле утилит C (getopt)?

Модуль getopt (унаследован от Unix-традиции) позволяет разбирать опции с одним дефисом (-o) и двумя (--output), но требует ручного разделения на опции и позиционные аргументы. Часто считается устаревшим, но может встречаться в старом коде.

import sys, getopt

try:
    opts, args = getopt.getopt(sys.argv[1:], 'o:v', ['output=', 'verbose'])
except getopt.GetoptError as err:
    print('Ошибка:', err)
    sys.exit(2)
for opt, arg in opts:
    if opt in ('-o', '--output'):
        print('Выходной файл:', arg)
    elif opt in ('-v', '--verbose'):
        print('Подробный режим')
print('Остальные аргументы:', args)

Python system path (системные вызовы и файловая система в python)

Пояснение: строка 'o:v' описывает короткие опции, где двоеточие означает обязательное значение. Длинные опции передаются списком. Ошибки обрабатываются вручную.

Недостатки: нет автоматической справки, нет проверки типов, легко перепутать регистр. Рекомендуется использовать только для обратной совместимости.

Как создать современный CLI с декораторами и минимальным кодом?

Библиотека click (сторонняя, но очень популярная) предлагает декларативный подход. Достаточно обернуть функцию декораторами, и click автоматически генерирует парсер и справку.

import click

@click.command()
@click.argument('input_file')
@click.option('-o', '--output', default='result.txt', help='Файл для записи')
@click.option('--verbose', is_flag=True, help='Подробный вывод')
def process(input_file, output, verbose):
    print(f'Вход: {input_file}')
    print(f'Выход: {output}')
    if verbose:
        print('Детализация включена')

if __name__ == '__main__':
    process()

Python py file system (работа с файловой системой в python (os, shutil))

Цели: быстрое создание сложных интерфейсов, встроенная поддержка цветного вывода, групп команд, подсказок. Широко применяется в утилитах DevOps.

Потенциальная сложность - необходимость установки (pip install click). Также трудно переопределить стандартные сообщения об ошибках.

Как парсить аргументы на основе документации в стиле help (docopt)?

docopt (сторонний модуль) анализирует строку справки, написанную в определённом формате, и автоматически строит парсер. Идеально, если хочется писать справку и получать парсинг без дополнительного кода.

"""
Использование: my_script <file> [-o OUTPUT] [--verbose]

Опции:
  -o OUTPUT  Выходной файл
  --verbose  Детализация
"""
from docopt import docopt

if __name__ == '__main__':
    arguments = docopt(__doc__)
    print('Файл:', arguments['<file>'])
    print('Выход:', arguments['-o'])
    print('verbose:', arguments['--verbose'])

Пояснение: строка документации __doc__ содержит синтаксис, схожий с man-страницами. docopt сам определяет типы (обязательные, опциональные, списки).

Ограничения: сложно настроить валидацию типов (например, int). Также при изменении справки нужно вручную обновлять шаблон. Библиотека почти не поддерживается с 2016 года.

Расширенные примеры обработки аргументов командной строки

Пример 1: argparse с подкомандами и взаимно исключающими опциями

Данный пример демонстрирует создание CLI с двумя подкомандами (start, stop) и взаимоисключающими флагами (-s для start, -x для stop).

Пример
import argparse

parser = argparse.ArgumentParser(description='Управление сервисом')
subparsers = parser.add_subparsers(dest='command', help='Доступные команды')

# Подкоманда start
start_parser = subparsers.add_parser('start', help='Запуск сервиса')
start_parser.add_argument('-d', '--daemon', action='store_true', help='Запустить в фоне')

# Подкоманда stop
stop_parser = subparsers.add_parser('stop', help='Остановка сервиса')
stop_parser.add_argument('-f', '--force', action='store_true', help='Принудительная остановка')

# Взаимоисключающие опции для главной команды
group = parser.add_mutually_exclusive_group()
group.add_argument('-s', '--start', action='store_true', help='Запуск')
group.add_argument('-x', '--stop', action='store_true', help='Остановка')

args = parser.parse_args()
if args.command == 'start':
    print('Команда start с флагом daemon =', args.daemon)
elif args.command == 'stop':
    print('Команда stop с флагом force =', args.force)
else:
    print('Общие флаги: start =', args.start, ', stop =', args.stop)

Результат выполнения:

$ python example1.py start -d
Команда start с флагом daemon = True

$ python example1.py -s
Общие флаги: start = True , stop = False

$ python example1.py -s -x
usage: example1.py [-h] [-s | -x] {start,stop} ...
example1.py: error: argument -x: not allowed with argument -s

Пример 2: click с группами команд и опциями с выбором из списка

Используется click версии 8.x. Показывает создание группы команд (config, run) и ограничение значений через click.Choice.

Пример
import click

@click.group()
def cli():
    pass

@cli.command()
@click.option('--mode', type=click.Choice(['dev', 'prod'], case_sensitive=False),
              default='dev', help='Режим работы')
def config(mode):
    """Настройка режима работы"""
    click.echo(f'Выбран режим: {mode}')

@cli.command()
@click.argument('script', type=click.Path(exists=True))
@click.option('--iterations', default=10, help='Количество итераций')
def run(script, iterations):
    """Запуск скрипта с заданными итерациями"""
    click.echo(f'Запуск {script} с {iterations} итерациями')

if __name__ == '__main__':
    cli()
$ python example2.py config --mode prod
Выбран режим: prod

$ python example2.py run my_script.py --iterations 5
Запуск my_script.py с 5 итерациями

$ python example2.py config --mode staging
Usage: example2.py config [OPTIONS]
Try 'example2.py config --help' for help.
Error: Invalid value for '--mode': 'staging' is not one of 'dev', 'prod'.

Пример 3: docopt с обработкой позиционных аргументов и флагов

Пример демонстрирует парсинг текстовой справки, где аргументы могут повторяться (как в командах копирования).

Пример
"""
Копирование файлов.

Использование:
  copy <source> <dest> [--backup]
  copy --list

Опции:
  -b, --backup  Создать резервную копию
  --list        Показать список файлов
"""
from docopt import docopt

if __name__ == '__main__':
    args = docopt(__doc__)
    if args['--list']:
        print('Вывод списка файлов')
    else:
        print(f'Копирование из {args["<source>"]} в {args["<dest>"]}')
        if args['--backup']:
            print('Создание резервной копии')
$ python example3.py file1.txt file2.txt --backup
Копирование из file1.txt в file2.txt
Создание резервной копии

$ python example3.py --list
Вывод списка файлов

Пример 4: sys.argv и ручной разбор с обработкой ошибок

Полный разбор аргументов через sys.argv без сторонних модулей: поддержка ключа -o и позиционного файла.

Пример
import sys

def main():
    argv = sys.argv[1:]
    if not argv:
        print('Ошибка: не указан файл. Использование: script.py  [-o out]')
        sys.exit(1)
    
    output = None
    positional = []
    i = 0
    while i < len(argv):
        if argv[i] == '-o':
            i += 1
            if i >= len(argv):
                print('Ошибка: после -o ожидается значение')
                sys.exit(1)
            output = argv[i]
        else:
            positional.append(argv[i])
        i += 1
    
    if not positional:
        print('Ошибка: не указан источник')
        sys.exit(1)
    
    print('Файл:', positional[0])
    if output:
        print('Выход:', output)

if __name__ == '__main__':
    main()
$ python example4.py data.txt -o result.log
Файл: data.txt
Выход: result.log

$ python example4.py
Ошибка: не указан файл. Использование: script.py  [-o out]

Пример 5: getopt с обработкой нескольких значений для одной опции

Показывает, как с помощью getopt можно принимать несколько аргументов под одну опцию, используя повторение опции.

Пример
import sys, getopt

try:
    opts, args = getopt.getopt(sys.argv[1:], 'i:', ['input='])
except getopt.GetoptError as err:
    print(err)
    sys.exit(2)

inputs = []
for opt, arg in opts:
    if opt in ('-i', '--input'):
        inputs.append(arg)

print('Входные файлы:', inputs)
print('Позиционные аргументы:', args)
$ python example5.py -i file1.txt -i file2.txt --input file3.txt other
Входные файлы: ['file1.txt', 'file2.txt', 'file3.txt']
Позиционные аргументы: ['other']

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

En
аргументы программы python (python)