Настройка параметров при запуске Python скрипта

Раздел: Python -> Инструкции по запуску

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

Параметры запуска позволяют изменять поведение программы без изменения кода. Python предоставляет несколько механизмов для их получения: от простого списка sys.argv до мощного парсера argparse. Выбор метода зависит от сложности проекта и требуемой гибкости. Рассмотрим каждый подход с примерами и разбором типичных затруднений.

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

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


import argparse

parser = argparse.ArgumentParser(description='Пример программы с параметрами')
parser.add_argument('--name', type=str, default='мир', help='Имя для приветствия')
parser.add_argument('--count', type=int, default=1, help='Количество повторений')
parser.add_argument('--verbose', action='store_true', help='Подробный вывод')

args = parser.parse_args()

for i in range(args.count):
    msg = f'Привет, {args.name}!'
    if args.verbose:
        msg = f'{i+1}. {msg}'
    print(msg)

параметры запуска программы python (параметры запуска программы python)

$ python script.py --name Алексей --count 3 --verbose
1. Привет, Алексей!
2. Привет, Алексей!
3. Привет, Алексей!

В примере заданы три аргумента: строковый --name, целочисленный --count и флаг --verbose. Модуль автоматически генерирует справку (-h) и проверяет типы.

Типичные ошибки:

  • Передача строки вместо числа для --count - argparse выведет сообщение об ошибке и завершит программу.
  • Забыли использовать type= - все аргументы остаются строками, что приводит к логическим ошибкам.
  • Конфликт имен - если два параметра имеют одинаковую строку-флаг, argparse выбросит исключение ArgumentError.

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

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


import sys

print('Имя скрипта:', sys.argv[0])
print('Аргументы:', sys.argv[1:])
$ python script.py one two three
Имя скрипта: script.py
Аргументы: ['one', 'two', 'three']

Подходит для простых скриптов с фиксированной позицией аргументов.

Возможные сложности:

  • Отсутствие проверки типа - все элементы строки, даже если ожидалось число.
  • Жёсткая привязка к порядку аргументов - неудобно при добавлении новых опций.
  • Аргументы с пробелами нужно заключать в кавычки, иначе они будут разбиты.

Как разобрать короткие и длинные опции в стиле Unix без использования сторонних библиотек?

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


import sys
import getopt

opts, args = getopt.getopt(sys.argv[1:], 'o:v', ['output=', 'verbose'])
for opt, val in opts:
    if opt in ('-o', '--output'):
        print(f'Файл вывода: {val}')
    elif opt in ('-v', '--verbose'):
        print('Режим подробного вывода')
$ python script.py -o log.txt -v --output other.txt
Файл вывода: log.txt
Режим подробного вывода
Файл вывода: other.txt

Опции задаются строкой коротких и списком длинных. Значения отделяются двоеточием.

Недостатки:

  • Ручная обработка ошибок - неверный аргумент вызывает GetoptError.
  • Нет автоматической проверки типов, всё остаётся строками.
  • Сложность поддержки для большого количества опций.

Как задать параметры через переменные окружения, не передавая их в командной строке?

Переменные окружения удобны для конфигурации, которая не должна меняться между запусками. Чтение выполняется через os.environ.


import os

name = os.environ.get('MY_NAME', 'гость')
level = int(os.environ.get('LOG_LEVEL', '1'))
print(f'Привет, {name}! Уровень лога: {level}')
$ export MY_NAME='Сергей'
$ export LOG_LEVEL=3
$ python script.py
Привет, Сергей! Уровень лога: 3

Значение по умолчанию задаётся вторым аргументом get. Преобразование типов выполняется вручную.

Ошибки и ограничения:

  • Все значения - строки; если LOG_LEVEL не задан или не число, int() вызовет исключение.
  • Переменные окружения могут быть случайно унаследованы от других процессов.
  • Неудобно передавать сложные структуры (списки, словари).

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

Многоуровневый разбор с подкомандами через argparse

Пример программы для работы с задачами: добавление, удаление, список. Подкоманды реализованы через add_subparsers.

Пример

import argparse

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

# Команда add
parser_add = subparsers.add_parser('add', help='Добавить задачу')
parser_add.add_argument('-t', '--title', required=True, help='Название задачи')
parser_add.add_argument('-p', '--priority', type=int, default=0, help='Приоритет')

# Команда remove
parser_remove = subparsers.add_parser('remove', help='Удалить задачу')
parser_remove.add_argument('id', type=int, help='Идентификатор задачи')

# Команда list
parser_list = subparsers.add_parser('list', help='Показать все задачи')
parser_list.add_argument('--all', action='store_true', help='Показать выполненные')

args = parser.parse_args()

if args.command == 'add':
    print(f'Добавлена задача "{args.title}" с приоритетом {args.priority}')
elif args.command == 'remove':
    print(f'Удалена задача с id={args.id}')
elif args.command == 'list':
    print('Список задач' + (', включая выполненные' if args.all else ''))
else:
    parser.print_help()
$ python todo.py add -t "Купить молоко" -p 2
Добавлена задача "Купить молоко" с приоритетом 2
$ python todo.py remove 5
Удалена задача с id=5
$ python todo.py list --all
Список задач, включая выполненные

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

Параметр nargs позволяет принимать несколько значений. Например, передача списка имён.

Пример

import argparse

parser = argparse.ArgumentParser()
parser.add_argument('--names', nargs='+', help='Одно или несколько имён')
parser.add_argument('--age', type=int, nargs='?', const=25, help='Возраст (опциональный)')

args = parser.parse_args()
print('Имена:', args.names)
print('Возраст:', args.age)
$ python multi.py --names Анна Иван Петр --age 30
Имена: ['Анна', 'Иван', 'Петр']
Возраст: 30
$ python multi.py --names Ольга
Имена: ['Ольга']
Возраст: 25   (значение по умолчанию const)

Чтение параметров из конфигурационного файла

Иногда удобнее хранить параметры в файле. Используем argparse вместе с чтением JSON.

Пример

import argparse
import json

parser = argparse.ArgumentParser()
parser.add_argument('--config', type=str, help='Путь к JSON конфигу')
parser.add_argument('--host', type=str)
parser.add_argument('--port', type=int)

args = parser.parse_args()

if args.config:
    with open(args.config, 'r') as f:
        config = json.load(f)
    # Значения из командной строки имеют приоритет
    for key, val in vars(args).items():
        if val is None and key in config:
            setattr(args, key, config[key])

print(f'Хост: {args.host}, Порт: {args.port}')
$ echo '{"host": "localhost", "port": 8080}' > config.json
$ python with_config.py --config config.json --port 9000
Хост: localhost, Порт: 9000

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

Пользовательские действия в argparse

Можно создать свой класс действия для нестандартной обработки, например, для накопления значений в список.

Пример

import argparse

class AppendListAction(argparse.Action):
    def __call__(self, parser, namespace, values, option_string=None):
        current = getattr(namespace, self.dest, [])
        current.extend(values)
        setattr(namespace, self.dest, current)

parser = argparse.ArgumentParser()
parser.add_argument('--items', nargs='+', action=AppendListAction, help='Добавить элементы')

args = parser.parse_args()
print('Собранные элементы:', args.items)
$ python custom_action.py --items a b --items c d
Собранные элементы: ['a', 'b', 'c', 'd']

Обработка параметров с помощью sys.argv вручную

Иногда требуется минимальный парсинг без импорта сторонних модулей. Пример: поиск флага -v и значения после --file.

Пример

import sys

verbose = False
filename = None
i = 1
while i < len(sys.argv):
    arg = sys.argv[i]
    if arg == '-v':
        verbose = True
    elif arg == '--file':
        i += 1
        if i < len(sys.argv):
            filename = sys.argv[i]
        else:
            sys.exit('Не указано имя файла после --file')
    else:
        sys.exit(f'Неизвестный аргумент: {arg}')
    i += 1

print(f'Verbose: {verbose}, File: {filename}')
$ python manual.py -v --file data.txt
Verbose: True, File: data.txt

Комбинирование переменных окружения и argparse

Часто практикуется поддержка нескольких источников параметров с приоритетом: командная строка переопределяет переменные окружения.

Пример

import argparse
import os

parser = argparse.ArgumentParser()
parser.add_argument('--database-url', type=str, default=os.environ.get('DB_URL'))
parser.add_argument('--debug', action='store_true', default=os.environ.get('DEBUG', '0') == '1')

args = parser.parse_args()
print(f'URL базы: {args.database_url}')
print(f'Отладка: {args.debug}')
$ export DB_URL='postgres://user:pass@localhost/db'
$ export DEBUG=1
$ python combined.py --debug
URL базы: postgres://user:pass@localhost/db
Отладка: True
$ python combined.py --database-url 'sqlite:///test.db'
URL базы: sqlite:///test.db
Отладка: False

Параметры запуска программы Python - comments

En
параметры запуска программы python (python)