Aşırı karmaşık basit şeyler konusundaki sonsuz arayışımda , Python yumurta paketlerinde bulunan tipik ' config.py ' içinde global yapılandırma değişkenleri sağlamak için en 'Pythonic' yolunu araştırıyorum .
Geleneksel yöntem (aah, good ol ' #define !) Aşağıdaki gibidir:
MYSQL_PORT = 3306
MYSQL_DATABASE = 'mydb'
MYSQL_DATABASE_TABLES = ['tb_users', 'tb_groups']
Bu nedenle global değişkenler aşağıdaki yollardan biriyle içe aktarılır:
from config import *
dbname = MYSQL_DATABASE
for table in MYSQL_DATABASE_TABLES:
print table
veya:
import config
dbname = config.MYSQL_DATABASE
assert(isinstance(config.MYSQL_PORT, int))
Bu mantıklı, ancak bazen biraz dağınık olabilir, özellikle belirli değişkenlerin adlarını hatırlamaya çalıştığınızda. Bunun yanı sıra, bir sağlama 'yapılandırma' nesne ile nitelikler gibi değişkenler , daha esnek olabilir. Böylece, bpython config.py dosyasından bir ipucu alarak şunu buldum :
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)])
ve sınıfı içe aktaran ve aşağıdaki gibi okuyan bir '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'
ve şu şekilde kullanılır:
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))
Bu, bir paket içindeki global değişkenleri depolamanın ve getirmenin daha okunaklı, anlamlı ve esnek bir yolu gibi görünüyor.
Hiç iğrenç bir fikir mi? Bu durumlarla başa çıkmak için en iyi uygulama nedir? Nedir sizin depolamak ve küresel isimleri ve değişkenleri paketinize getiriliyor yolu?