Аргументы командной строки: как их читать и использовать в коде

Раздел: Основы Python -> Аргументы командной строки

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

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

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

import argparse

parser = argparse.ArgumentParser(description='Пример скрипта с аргументами')
parser.add_argument('input_file', help='Путь к входному файлу')
parser.add_argument('--verbose', '-v', action='store_true', help='Подробный вывод')
parser.add_argument('--count', type=int, default=1, help='Количество повторений')

args = parser.parse_args()
print(f'Обрабатываю файл: {args.input_file}')
if args.verbose:
    print('Режим подробного вывода включён')
for i in range(args.count):
    print(f'Шаг {i+1}')

Python arguments (передача аргументов в python скрипт)

После определения парсера вызывается метод parse_args(), который анализирует содержимое sys.argv. При наличии ошибок (неверный тип, отсутствие обязательного аргумента) выводится сообщение и скрипт завершается.

Типичные проблемы:

  • Забыли указать обязательный позиционный аргумент - argparse выведет справку и завершит программу с кодом 2.
  • Передали неверный тип данных (например, строку вместо числа) - возникает ошибка разбора с указанием ожидаемого типа.
  • Попытка использовать аргумент, который не был определён - argparse по умолчанию завершает программу с сообщением об ошибке.

Решение: внимательно определять типы через type=, задавать default для необязательных аргументов и проверять логику значений после парсинга.

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

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

import sys

args = sys.argv[1:]  # отбрасываем имя скрипта
if len(args) < 1:
    print('Ошибка: укажите имя файла')
    sys.exit(1)
filename = args[0]
print(f'Файл для обработки: {filename}')

Проблемы: нет автоматической проверки типов и справки; при отсутствии аргументов возникает IndexError без пояснений; флаги типа --verbose нужно разбирать вручную.

Решение: использовать argparse или, для простых случаев, проверять len(sys.argv) и выполнять примитивный парсинг.

Как сделать интерфейс командной строки с подкомандами и автоматической справкой?

Библиотека click (сторонняя) позволяет создавать сложные CLI с помощью декораторов. Она поддерживает группы команд, подкоманды, типы аргументов, опции и контекст.

import click

@click.command()
@click.argument('name')
@click.option('--greeting', default='Hello', help='Приветственное слово')
@click.option('--count', default=1, type=int)
def greet(name, greeting, count):
    for i in range(count):
        print(f'{greeting}, {name}! (шаг {i+1})')

if __name__ == '__main__':
    greet()

Установка: pip install click.

Ошибки: неверные имена аргументов или опций приводят к исключениям; отсутствует проверка типов, если не указан type.

Решение: чётко определять @click.argument и @click.option, использовать тип int, float, Path и т.д.

Как обрабатывать аргументы в стиле Unix getopt?

Модуль getopt реализует парсинг коротких и длинных опций по аналогии с C-функцией getopt. Он прост, но менее удобен, чем argparse.

import sys
import getopt

try:
    opts, args = getopt.getopt(sys.argv[1:], 'ho:v', ['help', 'output=', 'verbose'])
except getopt.GetoptError:
    print('Ошибка разбора опций')
    sys.exit(2)

output_file = None
verbose = False
for opt, arg in opts:
    if opt in ('-h', '--help'):
        print('Справка: ...')
        sys.exit(0)
    elif opt in ('-o', '--output'):
        output_file = arg
    elif opt in ('-v', '--verbose'):
        verbose = True

print(f'Output: {output_file}, Verbose: {verbose}')
print(f'Остальные аргументы: {args}')

Проблемы: отсутствие автоматической справки; нужно вручную обрабатывать опции; исключения при неверных опциях; нет проверки типов.

Решение: для новых проектов рекомендуется argparse или click.

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

argparse: подкоманды и проверка существования файла

Следующий пример демонстрирует создание инструмента с двумя подкомандами: read и write. При этом позиционный аргумент file проверяется на существование (для команды read).

Пример
import argparse
import os

def file_exists(path):
    if not os.path.isfile(path):
        raise argparse.ArgumentTypeError(f'Файл {path} не найден')
    return path

parser = argparse.ArgumentParser(description='Утилита для работы с файлами')
subparsers = parser.add_subparsers(dest='command', required=True)

parser_read = subparsers.add_parser('read', help='Прочитать файл')
parser_read.add_argument('file', type=file_exists, help='Путь к файлу')
parser_read.add_argument('--encoding', default='utf-8', help='Кодировка')

parser_write = subparsers.add_parser('write', help='Записать в файл')
parser_write.add_argument('file', help='Путь к файлу')
parser_write.add_argument('--content', required=True, help='Текст для записи')

args = parser.parse_args()

if args.command == 'read':
    with open(args.file, 'r', encoding=args.encoding) as f:
        print(f.read())
elif args.command == 'write':
    with open(args.file, 'w', encoding='utf-8') as f:
        f.write(args.content)

Пример запуска:

$ python script.py read existing.txt --encoding cp1251
(содержимое файла)
$ python script.py write new.txt --content "Hello"
(файл создан)
$ python script.py read nonexistent.txt
usage: script.py read [-h] [--encoding ENCODING] file
script.py read: error: argument file: Файл nonexistent.txt не найден

sys.argv: ручной парсинг с поддержкой флагов

Без модулей реализуется разбор коротких флагов вида -v и длинных --output=file.

Пример
import sys

def parse_args():
    args = sys.argv[1:]
    flags = {}
    positional = []
    i = 0
    while i < len(args):
        if args[i].startswith('--'):
            if '=' in args[i]:
                key, val = args[i][2:].split('=', 1)
                flags[key] = val
            else:
                key = args[i][2:]
                if i+1 < len(args) and not args[i+1].startswith('-'):
                    flags[key] = args[i+1]
                    i += 1
                else:
                    flags[key] = True
        elif args[i].startswith('-'):
            for ch in args[i][1:]:
                flags[ch] = True
        else:
            positional.append(args[i])
        i += 1
    return flags, positional

flags, pos = parse_args()
print('Флаги:', flags)
print('Позиционные:', pos)

Результат работы:

$ python script.py -v --output=log.txt file1 file2
Флаги: {'v': True, 'output': 'log.txt'}
Позиционные: ['file1', 'file2']

click: группы команд и вложенные опции

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

Пример
import click

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

@click.command()
@click.argument('number', type=float)
def sqrt(number):
    import math
    click.echo(math.sqrt(number))

@click.command()
@click.argument('numbers', nargs=-1, type=float)
def multiply(numbers):
    result = 1
    for n in numbers:
        result *= n
    click.echo(result)

cli.add_command(sqrt)
cli.add_command(multiply)

if __name__ == '__main__':
    cli()

Примеры выполнения:

$ python script.py sqrt 16
4.0
$ python script.py multiply 2 3 4
24

getopt: обработка опций с обязательными аргументами

В getopt можно указать, что за некоторой опцией должен следовать аргумент, используя двоеточие в короткой строке или знак равенства в длинной.

Пример
import sys, getopt

try:
    opts, args = getopt.getopt(sys.argv[1:], 'i:o:', ['input=', 'output='])
except getopt.GetoptError:
    print('Ошибка')
    sys.exit(2)

input_file = None
output_file = None
for opt, arg in opts:
    if opt in ('-i', '--input'):
        input_file = arg
    elif opt in ('-o', '--output'):
        output_file = arg

print(f'input: {input_file}, output: {output_file}, остальное: {args}')
$ python script.py -i data.txt -o out.txt extra_arg
input: data.txt, output: out.txt, остальное: ['extra_arg']
$ python script.py -i data.txt        # -o не указан
input: data.txt, output: None, остальное: []

Передача аргументов в Python скрипт - comments

En
Python arguments (python)