LINUX.ORG.RU

Python скрипты с единой конфигурацией

 


1

5

Есть один python-проект для общения с сервисом в сети. Интерфейс выполнен в виде набора скриптов, причём одни скрипты используют разный набор модулей в проекте, т.е. одному скрипту нужен модуль для работы с БД и с сетью, другому просто покопаться в БД. Для настройки всего этого использую один файл настроек. При этом пытаюсь сделать чтобы все эти модули настраивались одной и той же процедурой:

    .
    ├── config.py
    ├── config.ini
    ├── script.py
    ├── db_module
    │   ├── __init__.py
    │   ├── config.py
    │   └── db_api.py
    └── rpc_module
        ├── __init__.py
        ├── config.py
        └── fetch.py
#!/usr/bin/env python3

from pprint import pprint

from rpc_module.fetch import fetch_some
import config


config.configure(config_file = "init.ini")

pprint(fetch_some())

Может конечно config в корне загрузить config каждого модуля, каждый из которых настроит переменные в коде каждого модуля, но таким образом загрузится почти весь код всех модулей, что далеко не каждому скрипту нужно. Пока решил, что init.py каждого модуля добавляет процедуру настройки в список из корневого config.py, а единая процедура просто запускает все процедуры в этом списке:

## __init__.py
from ..config import __configurators
from .config import configure

__configurators.append(configure)
## config.py
from collections import deque
from configparser import ConfigParser

__configurators = deque()


def read (f = "config.ini"):
    c = ConfigParser()
    c.read(f)
    return c

def configure (config_file = None):
    if config_file is None:
        config = read()
    else:
        config = read(config_file)
    for configurator in __configurators:
        configurator(config)

Получаю:

ImportError: attempted relative import beyond top-level package

Гугл подсказывает как обойти это хаком с sys.path, но может есть другие решения?

★★★★★

Последнее исправление: ados (всего исправлений: 1)

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

AntonI ★★★★
()
Ответ на: комментарий от vvn_black

Это нормально совать пароли доступа в переменные окружения?

Или каждый модуль должен по своему читать один и тот же файл настроек?

ados ★★★★★
() автор топика
Последнее исправление: ados (всего исправлений: 1)
Ответ на: комментарий от ados

Это нормально совать пароли доступа в переменные окружения?

Нормально.

Или каждый модуль должен по своему читать один и тот же файл настроек?

Вы читаете настройки один раз, причём всё-равно откуда - yaml, ini, env, переменные. Потом вы структуру с настройками раскидываете по модулям, через механизм DI например или глобально, как например в aiohttp сделано через экземпляр приложения. Это если у вас «единая точка входа».

Если у вас модули запускаются независимо друг от друга, то, конечно, каждый из них должен уметь читать настройки или импортировать такую читалку в качестве зависимости.

То, что каждому отдельному модулю будут доступны все настройки, ну так вы же в доверенном окружении запускаете?

Или, через те же переменные, каждый модуль знает что ему нужно получить из окружения.

vvn_black ★★★★★
()
Последнее исправление: vvn_black (всего исправлений: 1)
Ответ на: комментарий от ados

А зачем по-своему? Что нельзя это добро в один модуль вынести который умеет читать и работать с файлом настроек и где надо его импортировать и дёргать из него нужные методы классов/функции?

peregrine ★★★★★
()

Какая-то ода тупаку у меня получается. Запуск скрипта сам без всяких ковыряний прописывает директорию с config.py в sys.path, надо просто в __init__.py:

from ..config import __configurators

заменить на

from config import __configurators

и всё работает.

ados ★★★★★
() автор топика
Последнее исправление: ados (всего исправлений: 1)