La plupart des Pythonic façon globale les variables de configuration dans config.py?

Dans ma quête sans fin en plus de compliquer les choses simples, je suis la recherche de la plupart des "Pythonic de façon à assurer la configuration globale des variables à l'intérieur de la typique" config.py " qui se trouve en Python oeuf paquets.

De façon traditionnelle (aah, good ol' #define!) est comme suit:

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

Par conséquent, les variables globales sont importés dans l'une des façons suivantes:

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

ou:

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

C'est logique, mais parfois peut être un peu salissant, surtout quand vous êtes à essayer de se rappeler les noms de certaines variables. En outre, prévoir un 'configuration' objet, avec variables comme des attributs, peut-être plus flexible. Alors, prenant une avance de bpython config.py fichier, je suis venu avec:

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)])

et un "config.py" qu'importe la classe et se lit comme suit:

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'

et est utilisé de cette façon:

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))

Qui semble plus lisible, de l'expressivité et de manière flexible de stockage et de récupération des variables globales à l'intérieur d'un package.

Lamest idée jamais? Quelle est la meilleure pratique pour faire face à ces situations? Qu'est-ce que votre moyen de stocker et de récupérer des noms globales et les variables à l'intérieur de votre colis?

  • Vous avez déjà pris une décision d'ici qui peut ou peut ne pas être bon. La config en elle-même peuvent être stockés de différentes manières, comme JSON, XML, différentes grammaires pour *nixes et Windows et ainsi de suite. Fonction qui écrit le fichier de config ( un outil, un homme, quel contexte?) différentes grammaires serait peut-être préférable. Le plus souvent, il pourrait ne pas être une bonne idée de laisser le fichier de config être rédigée dans la même langue que vous utilisez pour votre programme, parce qu'il donne trop de pouvoir à l'utilisateur (ce qui pourrait être vous-même, mais vous-même ne pourriez pas vous souvenir de tout ce qui peut mal se passer quelques mois à l'avance).
  • Souvent j'arrive à la fin de l'écriture d'un fichier de configuration JSON. Il peut être lu en python structures facilement et aussi être créé par un outil. Il semble avoir le plus de flexibilité et le coût sont certains de l'appareil qui peut être gênant pour l'utilisateur. Je n'ai jamais écrit un Oeuf, bien que. Peut-être que c'est la façon standard. Dans ce cas, il suffit de les ignorer mon commentaire ci-dessus.
  • Vous pouvez utiliser "vars(auto)" au lieu de "self.__dict__.les touches()"
  • Double Possible de What les bonnes pratiques à appliquer à l'aide d'un fichier de paramètres en Python? on répond "de Nombreuses voies sont possibles, et un bikeshed thread existe déjà. config.py est bon, à moins que vous vous souciez de la sécurité."