Как создать файл конфигурации в Python, где нужно иметь os.path.join?

У меня есть пара модулей Python, например:

prepare_data.py process_data.py generate_report.py

Я беру файл Excel, обрабатываю его и затем создаю отчет в формате .pdf. Это очень линейное процедурное программирование. В основном модуле caller.py я вызываю функции одну за другой:

prepare_data.do1() prepare_data.do2() generate_report.do3()

и т.п.

У меня также есть модуль Configuration.py, в котором я храню глобальные переменные и настройки, импортированные в prepare_data.py, process_data.py и generate_report.py.

Однако во время выполнения я создаю несколько промежуточных файлов в той же папке, где хранится файл Excel. В Configuration.py очень удобно иметь несколько переменных, которые создаются на основе расположения исходного файла Excel:

excel_file = r"C:\Data\InData.xlsx"
scratch_folder = os.path.dirname(excel_file)
out_pdf = os.path.join(scratch_folder,'PdfReport.pdf')

#scratch_folder is C:\Data

Затем в модулях, которые фактически выполняют работу, я хотел бы импортировать Configuration.py, а затем использовать переменные из этого модуля:

... import Configuration as cfg create_pdf(cfg.out_pdf) ...

Однако, поскольку я вызываю caller.py и предоставляю в качестве аргумента путь к файлу Excel, я не могу сохранить путь к файлу Excel в Configuration.py.

Если я использую такие решения, как ConfigParser или просто обычный файл .conf, если я правильно понимаю, я не могу воспользоваться из os.path.join() и других функций Python для построения путей.

Что было бы эффективным способом организации конфигураций в моем конкретном случае?


person Alex Tereshenkov    schedule 21.12.2016    source источник


Ответы (1)


Не могли бы вы создать класс?

в Configuration.py вы просто объявите переменную:

foo = None

В вашей основной программе вы должны объявить класс, и как только у вас появится путь к файлу excel_file, создайте экземпляр:

class ExcelFileClass(object):
    def __init__(self, ef):
        self.scratch_folder = os.path.dirname(ef)
        ...

Configuration.foo = ExcelFileClass(excel_file)

В каждом модуле, импортирующем конфигурацию, вы сможете получить доступ к Configuration.foo.scratch_folder и другим переменным класса. Вы также можете добавить метод get, если хотите выполнить проверку, обработку ошибок или что-то еще для переменных вашего класса.

Ханну

person Hannu    schedule 21.12.2016
comment
Спасибо за публикацию. Я решил использовать глобальные переменные из модуля, например stackoverflow.com/a/13034908/3346915. Мне нравится иметь класс конфигурации, как вы описали, однако необходимость вводить config.cfg.folder_name болезненна. Есть ли способ сократить это? Очевидно, я не могу сделать from Configuration import cfg, так как это изначально импортирует None. - person Alex Tereshenkov; 02.02.2017
comment
Чтобы не усложнять, нет. Вы можете динамически импортировать переменные без префикса, но это просто добавляет код. Если вы переименуете Configuration.py в C.py или что-то в этом роде, C.foo не будет слишком сильно отличаться от foo. Вот как я это делаю во всяком случае. - person Hannu; 02.02.2017
comment
Спасибо, что поделился. Итак, если бы вам нужно было получить доступ к scratch_folder из некоторых модулей, вы бы вызвали C.foo.scratch_folder, верно? - person Alex Tereshenkov; 02.02.2017
comment
Так и должно быть. Вам просто нужно добавить файл конфигурации к вашим глобальным переменным в качестве префикса. Не оптимально, но легко реализовать и не требует каких-либо уловок. Также легко отлаживать, если что-то не то, чем кажется. - person Hannu; 02.02.2017
comment
Большое спасибо, я тебя понял. Поскольку никто другой не предложил никакого решения, я принял ваше. - person Alex Tereshenkov; 02.02.2017