Python 如何在每次读取时更新配置?

Python 如何在每次读取时更新配置?,python,python-3.x,yaml,pyyaml,Python,Python 3.x,Yaml,Pyyaml,所以我有一节课: import yaml class Config(): def __init__(self, filename): self.config_filename=filename def __read_config_file(self): with open(self.config_filename) as f: self.cfg =

所以我有一节课:

import yaml

class Config():
        def __init__(self, filename):
                self.config_filename=filename

        def __read_config_file(self):
                with open(self.config_filename) as f:
                        self.cfg = yaml.safe_load(f)

        def get(self):
                self.__read_config_file()
                return self.cfg
而且效果很好。其背后的思想是每次使用配置中的某些内容时都强制重新读取配置文件。下面是一个用法示例:

cfg = Config('myconfig.yaml')

for name in cfg.get()['persons']:
    print (cfg.get()['persons'][name]['phone']) 
    print (cfg.get()['persons'][name]['address']) 
这是可行的,但我觉得它看起来非常难看。我可以这样做:

c = cfg.get()['persons']
for name in c:
    print (c['persons'][name]['phone']) 
    print (c['persons'][name]['address']) 
这看起来只是稍微好一点,但我也失去了在access上重新加载的好处,但我想做的是这样的事情(这显然不起作用):

似乎我不理解在字典上迭代,但我主要关心的是,每次使用配置文件中的任何值时,我都要重新加载该配置文件,并且我希望它具有良好的可读性。那么我如何重新设计这个呢

配置文件的示例。如有必要,可以在此处更改格式

persons:
    john:
        address: "street A"
        phone: "123"
    george:
        address: "street B"
        phone: "456"

因为它是dict,所以正常的迭代不起作用。我们可以通过以下方法迭代字典

c.items()中的姓名、人物: 印刷品(名称) 打印(个人[“电话]) 打印(人员['地址])
希望这有帮助

我已经制作了您的“人员”数据:

persons={}
persons["name"]={"john":{'phone':'123', 'address':'street A'}, 
                 "george":{'phone':'456', 'address':'street B'}}
有趣的是,你可以得到所有写在“persons”中的名字:

因此,如果您获得每个字符的数据:

L_names_data = []
for i in list(persons['name'].keys()):
    L_names_data.append(persons['name'][i])
你可以很容易地写出你想要的:(一个漂亮而简单的for循环)


不便之处在于您丢失了“姓名”信息(“john”和“george”字符串不出现在“L_names_data”中,这是一个词汇列表)。

用户rasjani发表了一些评论,帮助我解决了这个问题。我基本上是这样做的:

import collections

class Config(collections.UserDict):
        def __getitem__(self, key):
                self.reload()
                return super().__getitem__(key)

        def reload(self):
                with open(self.filename) as f:
                        c=yaml.safe_load(f)
                super().__init__(c)
实际的类更复杂,有更多的错误检查和特性,但上面是我所问的魔术

每次使用字典时都会调用方法
\uuu getitem\uu
。因此,我所做的只是在从超类调用
\uu getitem\uuu
之前调用
reload

我们应该知道这里有一个例外

a = Config('myconf.yml')
b = a['field'] # Will reload the configuration file
c = a          # But this will not
d = c['field'] # However, this will

我曾想过通过同样的方式修改
\uuu getattribute\uuuu
来解决这个问题,但最终我遇到了各种各样的问题,比如无休止的递归,实际上我不确定这是否是一个值得解决的问题,甚至是一个问题。

YAML文件看起来像什么?@RoadRunner这真的很重要吗?但是好的,我会更新这个问题。看看这里,这可能会很有帮助:@klutt好的,它总是好的,包括一个示例文件。一些未来的读者可能对YAML不太熟悉,无法理解您的代码在做什么。我会让Config类成为UserDict的子类,然后覆盖
\uuu getitem\uuu()
,以便在返回值之前进行读取。这有点帮助,但这不会为每个打印语句重新加载配置文件,对吗?是的,不会。因为您已经创建了一个对象
cfg
,所以它将遍历该对象的值。
for name_data in L_names_data:
    print(name_data['address'])
    print(name_data['phone'])

#returns :
#street A
#123
#street B
#456
import collections

class Config(collections.UserDict):
        def __getitem__(self, key):
                self.reload()
                return super().__getitem__(key)

        def reload(self):
                with open(self.filename) as f:
                        c=yaml.safe_load(f)
                super().__init__(c)
a = Config('myconf.yml')
b = a['field'] # Will reload the configuration file
c = a          # But this will not
d = c['field'] # However, this will