我被代码中的一个bug弄糊涂了:
使用distribute_tags
方法给出下面的类
class ConsulData:
def __init__(self, logger, marshalled_data, prom_numbering, prom_count):
self.logger = logger
self.current = marshalled_data
self.to_update= {}
self.payloads = []
self.prom_count = prom_count
self.prom_numbering = prom_numbering
def distribute_tags(self):
cpt = 0
cp_current = copy.deepcopy(self.current)
for keys, values in cp_current.items():
num = (cpt % self.prom_count) + self.prom_numbering
prometheus_tag = "prometheus-{}".format(num)
if not prometheus_tag in values['Tags']:
self.to_update[keys] = values
data = []
[data.append(v) for v in values['Tags'] if not v.startswith("prometheus")]
data.append(prometheus_tag)
self.to_update[keys]['Tags'] = data
cpt += 1
{...}
如果没有深度复制,则在循环执行之后,print(self.current == self.to_update)
返回True
。
print(id(self.current) == id(self.to_update))
返回False。
deepcopy
的使用修复了我意想不到的bug,因为在distribute_tags
内部所做的工作或多或少与执行的相同:
In [2]: d1 = {'key1':'value1', 'key2':'value2'}
In [3]: d2 = {}
In [4]: for k, v in d1.items():
...: d2[k] = v
In [6]: d2['key1'] = 'lol'
In [8]: d1
Out[8]: {'key1': 'value1', 'key2': 'value2'}
In [9]: d2
Out[9]: {'key1': 'lol', 'key2': 'value2'}
其中,d1数据不受对d2的修改的影响,因为它们是对不同对象的两个不同的引用。
传递给init函数的如下所示:
payload = {
'service1': {
'ID': 'service1',
'Service': 'service1',
'Tags': ['sre-metrics', 'prometheus-2'],
'Meta': {
'env': 'dev',
'namespace': 'test',
'path': '/path1',
'svc': 'svc1',
'team': 'testing'},
'Port': 80,
'Address': 'test1.testing.org',
'Weights': {'Passing': 1, 'Warning': 1},
'EnableTagOverride': False
},
...
发布于 2020-09-01 14:18:38
如果你不做个深拷贝,
self.to_update[keys] = values
为同一个values
字典指定一个引用。当你晚些时候
self.to_update[keys]['Tags'] = data
你在修改那个字典,所以这两个值仍然相等。
https://stackoverflow.com/questions/63689220
复制相似问题