Большинство Pythonic способ предоставить глобальные переменные конфигурации в config.py?

В моем бесконечном поиске в чрезмерно усложняющих простых вещах я изучаю самый «Pythonic» способ предоставить глобальные переменные конфигурации внутри типичного « config.py », найденного в пакетах яиц Python.

Традиционный способ (aah, good ol ' #define !) Заключается в следующем:

MYSQL_PORT = 3306 MYSQL_DATABASE = 'mydb' MYSQL_DATABASE_TABLES = ['tb_users', 'tb_groups'] 

Поэтому глобальные переменные импортируются одним из следующих способов:

 from config import * dbname = MYSQL_DATABASE for table in MYSQL_DATABASE_TABLES: print table 

или:

 import config dbname = config.MYSQL_DATABASE assert(isinstance(config.MYSQL_PORT, int)) 

Это имеет смысл, но иногда может быть немного грязным, особенно когда вы пытаетесь запомнить имена определенных переменных. Кроме того, предоставление объекта конфигурации с переменными как атрибутами может быть более гибким. Итак, взяв на себя инициативу из файла config.py от bpython , я придумал:

 class Struct(object): def __init__(self, *args): self.__header__ = str(args[0]) if args else None def __repr__(self): if self.__header__ is None: return super(Struct, self).__repr__() return self.__header__ def next(self): """ Fake iteration functionality. """ raise StopIteration def __iter__(self): """ Fake iteration functionality. We skip magic attribues and Structs, and return the rest. """ ks = self.__dict__.keys() for k in ks: if not k.startswith('__') and not isinstance(k, Struct): yield getattr(self, k) def __len__(self): """ Don't count magic attributes or Structs. """ ks = self.__dict__.keys() return len([k for k in ks if not k.startswith('__')\ and not isinstance(k, Struct)]) 

и «config.py», который импортирует класс и читает следующее:

 from _config import Struct as Section mysql = Section("MySQL specific configuration") mysql.user = 'root' mysql.pass = 'secret' mysql.host = 'localhost' mysql.port = 3306 mysql.database = 'mydb' mysql.tables = Section("Tables for 'mydb'") mysql.tables.users = 'tb_users' mysql.tables.groups = 'tb_groups' 

и используется таким образом:

 from sqlalchemy import MetaData, Table import config as CONFIG assert(isinstance(CONFIG.mysql.port, int)) mdata = MetaData( "mysql://%s:%s@%s:%d/%s" % ( CONFIG.mysql.user, CONFIG.mysql.pass, CONFIG.mysql.host, CONFIG.mysql.port, CONFIG.mysql.database, ) ) tables = [] for name in CONFIG.mysql.tables: tables.append(Table(name, mdata, autoload=True)) 

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

Самая известная идея? Какова наилучшая практика для решения этих ситуаций? Каков ваш способ хранения и выбор глобальных имен и переменных внутри вашего пакета?

6 Solutions collect form web for “Большинство Pythonic способ предоставить глобальные переменные конфигурации в config.py?”

Я сделал это один раз. В конечном итоге я нашел свой упрощенный basicconfig.py, адекватный моим потребностям. Вы можете пройти в пространстве имен с другими объектами для ссылки, если вам нужно. Вы также можете передать дополнительные значения по умолчанию из своего кода. Он также отображает синтаксис стиля атрибута и отображения в один и тот же объект конфигурации.

Как насчет использования встроенных типов:

 config = { "mysql": { "user": "root", "pass": "secret", "tables": { "users": "tb_users" } # etc } } 

Вы получите доступ к следующим значениям:

 config["mysql"]["tables"]["users"] 

Если вы готовы пожертвовать потенциалом для вычисления выражений внутри вашего дерева конфигураций, вы можете использовать YAML и в итоге получить более читаемый конфигурационный файл следующим образом:

 mysql: - user: root - pass: secret - tables: - users: tb_users 

и используйте библиотеку PyYAML для удобного анализа и доступа к файлу конфигурации

Как и ответ Блюбба. Мне нравятся встроенные типы. Я предлагаю создать их с помощью лямбда-функций, если сможете. Как это:

 mkDict = lambda passwd, hair, name: {'passwd':passwd, 'hair':hair, 'name':name} #Col Names: Password Hair Color Real Name config = {'st3v3' : mkDict('password', 'blonde', 'Steve Booker'), 'blubb' : mkDict('12345678', 'black', 'Bubb Ohaal'), 'suprM' : mkDict('kryptonite', 'black', 'Clark Kent'), #... } 

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

Мне нравится это решение для небольших приложений :

 class App: __conf = { "username": "", "password": "", "MYSQL_PORT": 3306, "MYSQL_DATABASE": 'mydb', "MYSQL_DATABASE_TABLES": ['tb_users', 'tb_groups'] } __setters = ["username", "password"] @staticmethod def config(name): return App.__conf[name] @staticmethod def set(name, value): if name in App.__setters: App.__conf[name] = value else: raise NameError("Name not accepted in set() method") 

И тогда использование:

 if __name__ == "__main__": # from config import App App.config("MYSQL_PORT") # return 3306 App.set("username", "hi") # set new username value App.config("username") # return "hi" App.set("MYSQL_PORT", "abc") # this raises NameError 

.. вам это понравится, потому что:

  • использует переменные класса (нет объекта для прохождения / нет необходимости в одиночном режиме),
  • использует инкапсулированные встроенные типы и выглядит как () метод вызова App ,
  • имеет контроль над индивидуальной неизменяемой конфигурацией, изменяемые глобальные переменные являются наихудшим видом глобальных переменных .
  • способствует традиционному и хорошо названному доступу / удобочитаемости в исходном коде
  • является простым классом, но обеспечивает структурированный доступ , альтернативой является использование @property , но для этого требуется больше кода обработки переменной на элемент и основано на объектах.
  • требует минимальных изменений для добавления новых элементов конфигурации и установки их изменчивости.

–Edit– : для больших приложений сохранение значений в файле YAML (т.е. свойств) и чтение, которое в качестве неизменяемых данных является лучшим подходом (например , ответ blubb / ohaal ). Для небольших приложений это решение выше проще.

Как насчет использования классов?

 # config.py class MYSQL: PORT = 3306 DATABASE = 'mydb' DATABASE_TABLES = ['tb_users', 'tb_groups'] # main.py from config import MYSQL print(MYSQL.PORT) # 3306 

пожалуйста, проверьте конфигурационную систему IPython, реализованную через traitsts для принудительного ввода типов вручную.

Вырезать и вставить здесь, чтобы соответствовать рекомендациям SO, а не просто отбрасывать ссылки, поскольку содержание ссылок изменяется с течением времени.

трассировать документацию

Вот основные требования, которые мы хотели, чтобы наша система конфигурации имела:

Поддержка иерархической информации конфигурации.

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

Файлы конфигурации, которые сами являются действительными Python-кодом. Это многое выполняет. Во-первых, становится возможным поставить логику в ваши файлы конфигурации, которая устанавливает атрибуты на основе вашей операционной системы, настройки сети, версии Python и т. Д. Во-вторых, Python имеет супер простой синтаксис для доступа к иерархическим структурам данных, а именно к регулярному доступу к атрибутам (Foo. Bar.Bam.name). В-третьих, использование Python упрощает пользователям импорт атрибутов конфигурации из одного конфигурационного файла в другой. В-четвертых, хотя Python динамически типизирован, он имеет типы, которые можно проверить во время выполнения. Таким образом, 1 в файле конфигурации представляет собой целое число «1», а «1» – строка.

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

Проверка типов и проверка, которые не требуют, чтобы вся иерархия конфигурации была задана статически до выполнения. Python – очень динамичный язык, и вы не всегда знаете все, что нужно настроить при запуске программы.

Чтобы добиться этого, они в основном определяют 3 класса объектов и их отношения друг к другу:

1) Конфигурация – в основном ChainMap / basic dict с некоторыми улучшениями для слияния.

2) Настраиваемый – базовый класс для подкласса всех вещей, которые вы хотите настроить.

3) Приложение – объект, который создается для выполнения определенной прикладной функции или основного приложения для одноцелевого программного обеспечения.

По их словам:

Применение: приложение

Приложение – это процесс, выполняющий определенную работу. Наиболее очевидным приложением является программа командной строки ipython. Каждое приложение считывает один или несколько файлов конфигурации и один набор параметров командной строки, а затем создает главный объект конфигурации для приложения. Затем этот объект конфигурации передается настраиваемым объектам, созданным приложением. Эти настраиваемые объекты реализуют реальную логику приложения и знают, как настроить себя с учетом объекта конфигурации.

Приложения всегда имеют атрибут журнала, который является настроенным Logger. Это позволяет централизованную конфигурацию протоколирования для каждого приложения. Конфигурируемый: настраиваемый

Конфигурируемый – это обычный класс Python, который служит базовым классом для всех основных классов в приложении. Настраиваемый базовый класс является легким и делает только одно.

Этот Configurable является подклассом HasTraits, который знает, как настроить себя. Значения уровня класса с конфигурацией метаданных = True становятся значениями, которые могут быть настроены из командной строки и файлов конфигурации.

Разработчики создают настраиваемые подклассы, реализующие всю логику приложения. Каждый из этих подклассов имеет свою собственную конфигурационную информацию, которая управляет созданием экземпляров.

Python - лучший язык программирования в мире.