Аргументы командной строки: как их читать и использовать в коде
Передача аргументов командной строки в 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, остальное: []