En mi búsqueda interminable de complicadas cosas simples, estoy investigando la forma más 'pitónica' de proporcionar variables de configuración globales dentro de la típica 'config.py' que se encuentra en los paquetes de Python.¿La forma más pitónica de proporcionar variables de configuración globales en config.py?
La forma tradicional (! Aah, buen ol' #define ) es el siguiente:
MYSQL_PORT = 3306
MYSQL_DATABASE = 'mydb'
MYSQL_DATABASE_TABLES = ['tb_users', 'tb_groups']
las variables globales Por lo tanto se importan en una de las siguientes maneras:
from config import *
dbname = MYSQL_DATABASE
for table in MYSQL_DATABASE_TABLES:
print table
o :
import config
dbname = config.MYSQL_DATABASE
assert(isinstance(config.MYSQL_PORT, int))
Tiene sentido, pero a veces puede b e un poco desordenado, especialmente cuando intenta recordar los nombres de ciertas variables. Además, proporcionar un objeto 'configuración', con variables como atributos, podría ser más flexible. Por lo tanto, tomando una ventaja de bpython archivo config.py, se me ocurrió:
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)])
y un 'config.py' que importa la clase y dice lo siguiente:
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'
y se utiliza de esta manera:
from sqlalchemy import MetaData, Table
import config as CONFIG
assert(isinstance(CONFIG.mysql.port, int))
mdata = MetaData(
"mysql://%s:%[email protected]%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))
que parece una manera más fácil de leer, expresivo y flexible de almacenamiento y ir a buscar variables globales dentro de un paquete.
Lamest idea ever? ¿Cuál es la mejor práctica para hacer frente a estas situaciones? ¿Qué es su forma de almacenar y buscar nombres y variables globales dentro de su paquete?
Usted ya tomó una decisión aquí que podría o no ser buena. La configuración en sí se puede almacenar de diferentes maneras, como JSON, XML, diferentes gramáticas para * nixes y Windows, y así sucesivamente. Dependiendo de quién escriba el archivo de configuración (una herramienta, un humano, ¿qué fondo?) Diferentes gramáticas podrían ser preferibles. Muy a menudo puede no ser una buena idea dejar que el archivo de configuración se escriba en el mismo idioma que usas para tu programa, ya que le da demasiada potencia al usuario (lo que podrías ser tú mismo, pero tú mismo podrías no recordar todo lo que pueda ir mal unos meses más adelante). – erikbwork
A menudo termino escribiendo un archivo de configuración JSON. Se puede leer fácilmente en las estructuras de python y también se puede crear con una herramienta. Parece tener la mayor flexibilidad y el único costo son algunas llaves que pueden ser molestas para el usuario. Aunque nunca escribí un huevo. Tal vez esa es la forma estándar. En ese caso, simplemente ignora mi comentario anterior. – erikbwork
Puede usar "vars (self)" en lugar de "self .__ dict __. Keys()" – Karlisson