我有很多函数来评估我的配置文件。 (在下面添加一些)
class Struct:
"""Returns an callable structure"""
def __init__(self, **entries):
self.__dict__.update(entries)
def read_config(filename):
"""Reads a config file.
:param filename: String with path to file name
:returns dict: Dict structure of config file
"""
try:
config_file = open(filename,'r')
try:
config = yaml.safe_load(config_file)
except yaml.YAMLError as e:
print "Error in configuration file:", e
sys.exit(e.errno)
finally:
config_file.close()
except ( IOError, OSError ) as e:
print "{0}: Error while openining configuration: {2}".format(__name__,
e.errno, e.strerror)
sys.exit(e.errno)
c = Struct(**config)
return c
def get_depot_param(depot,param):
"""Reads the param from configuration file. If does not exist returns the default.
:param depot: The depot to be read from config file
:retuns string: String with param
"""
try:
p = cfg.depots[depot][param]
except ( TypeError, KeyError) as e:
try:
# We failed to get the project regex. Fetching default.
p = getattr(cfg, param)
except KeyError as e:
# Default not defined
print "Error in configuration file: {0}: No default {1} defined. Please add a {1} entry on conf file".format(exc, param)
sys.exit(e.errno)
return p
读取的conf文件是一个yaml,格式如下:
loglevel: INFO
username: root
password: globalsecret
destdir: /dsk/bkpdir/
# Configurations here overwrites the defaults. The valid ones are:
# username, password, destdir
depots:
server1:
password: secret
server2:
username: root
server3:
server4:
destdir: /disk2/bkp/
如果未在库中设置配置,则可以使用“全局”配置。因为我创建的get_depot_param
会尝试阅读depot param(username
,password
,dstdir
和其他人。如果它没有在仓库中找到,请从全局抓取。
我经常将这些函数称为:
# To "initialize" the configurator descriptor
config_filename='backup.cfg'
cfg=read_config(config_filename)
# Calling one attribute from server2 (here I expect receive /dsk/bkpdir/)
get_depot_param('server2','destdir')
# Calling one attribute from server4 (here I expect receive /disk2/bkp)
get_depot_param('server4','destdir')
但是我开始将这些函数转换为类似的类:
import errno
import yaml
import sys
class Struct:
def __init__(self, **entries):
self.__dict__.update(entries)
class Config:
def __init__(self, filename="backup.cfg"):
try:
fd = open(filename,'r')
try:
yamlcfg = yaml.safe_load(fd)
except yaml.YAMLError as e:
sys.exit(e.errno)
finally:
fd.close()
except ( IOError, OSError ) as e:
sys.exit(e.errno)
self.cfg = Struct(**yamlcfg)
def __getattribute__(self, name):
try:
return object.__getattribute__(self, name)
except AttributeError:
return self.cfg.__getattribute__(name)
def depot_param(self,depot,param):
try:
self.depot_param = self.cfg.depots[depot][param]
except ( TypeError, KeyError) as e:
try:
self.depot_param = getattr(self.cfg, param)
except KeyError as e:
sys.exit(e.errno)
return self.depot_param
def project_param(self,project,param):
try:
self.project_param = self.cfg.projects[project][param]
except ( TypeError, KeyError) as e:
try:
self.project_param = getattr(self.cfg, param)
except KeyError as e:
sys.exit(e.errno)
return self.project_param
###################################################################################
if __name__ == '__main__':
# Read config file to cfg
config = Config()
#print config.loglevel
#print config.depot_param('server1','destdir')
#print config.depot_param('server2','destdir')
#print config.depot_param('server3','password')
我收到运行此代码:
# python backup.py
Traceback (most recent call last):
File "backup.py", line 59, in <module>
print config.loglevel
AttributeError: Config instance has no attribute 'loglevel'
答案 0 :(得分:2)
能够访问班级内的自定义属性并避免错误的命名问题。由您提供,我们将需要使用 getattribute (self,name)来完全控制新类。
一个例子;
class Config:
def __init__(self):
self.myItems = {'loglevel':'INFO'}
def __getattribute__(self, name):
try:
# get the class attributes as "priority", before anything else.
return object.__getattribute__(self, name)
except AttributeError:
# attribute was not found, try to get it from our list.
return self.myItems.get(name)
这将使我们能够做到,
config = Config()
print config.loglevel # output is INFO.
但是,它会在不存在的属性上返回None,您可以通过检查我们的字典是否包含它来转回异常,如果不再重新抛出它。
到目前为止,我还无法找到depot_param返回TypeError的任何问题。
编辑: depot_param中没有问题,在我的工作区中对其进行了测试。但是,以更好的方式快速获取属性的问题可以更快地解决您的问题;
def __getattribute__(self, name):
try:
# call superclass for attribute, they come in as priority.
return object.__getattribute__(self, name)
except AttributeError:
# call cfg for attribute, this would be like 'self.cfg.cfg.loglevel'
# but instead, 'self.cfg.loglevel'
return self.cfg.__getattribute__(name)