Настройка параметров при запуске 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