[英]RuntimeError dictionary changed size during iteration during dictionary iteration
运行我的代码时出现以下错误。 它开始发生,显然没有对代码进行任何更改。 该代码基本上尝试使用 jinja2 模板来渲染设备配置。
Traceback (most recent call last):
File "vdn_ler_generate_config.py", line 380, in <module>
lerConfig = lerTemplate.render(config=copy.copy(config.lerDevList[tLer]))
File "/Users/nileshkhambal/Documents/myansible/lib/python3.8/site-packages/jinja2/environment.py", line 1304, in render
self.environment.handle_exception()
File "/Users/nileshkhambal/Documents/myansible/lib/python3.8/site-packages/jinja2/environment.py", line 925, in handle_exception
raise rewrite_traceback_stack(source=source)
File "./templates/jinja2/JuniperLerConfigTemplate", line 71, in top-level template code
{%- for tBgpGrp in config.vrfs[tvrf].bgpProto %}
RuntimeError: dictionary changed size during iteration
下面“try”和“expect”块中的代码片段显示了这个问题。 第二个供应商有一个完全相同的代码,它工作正常。 在 expect 语句中使用 print 语句,我看到在迭代期间字典中添加了一个额外的组 object(带有“默认”)。 根据我的 YAML 配置,应该只有一个这样的组 object 应该在那里。
try:
if tVendor == 'VENDOR1':
lerTemplate = ENV.get_template('Vendor1LerConfigTemplate')
lerConfig = lerTemplate.render(config=config.lerDevList[tLer])
pOutputFile = './configs/' + str(tLer) + '.cfg'
with open(pOutputFile, "w+") as opHandle:
#print('Writing configuration for {}'.format(tLer))
opHandle.write(lerConfig)
opHandle.write('\n')
except:
for aKey in config.lerDevList[tLer].vrfs.keys():
#print(config.lerDevList[tLer].vrfs[aKey].bgpProto)
print('What VRF: {} How many BGP Groups: {}'.format(aKey,len(config.lerDevList[tLer].vrfs[aKey].bgpProto.keys())))
for agrp in config.lerDevList[tLer].vrfs[aKey].bgpProto.keys():
print(config.lerDevList[tLer].vrfs[aKey].bgpProto[agrp])
continue
if tVendor == 'VENDOR2':
for aKey in config.lerDevList[tLer].vrfs.keys():
#print(config.lerDevList[tLer].vrfs[aKey].bgpProto)
for agrp in config.lerDevList[tLer].vrfs[aKey].bgpProto.keys():
print(config.lerDevList[tLer].vrfs[aKey].bgpProto[agrp])
lerTemplate = ENV.get_template('Vendor2LerConfigTemplate')
lerConfig = lerTemplate.render(config=config.lerDevList[tLer])
pOutputFile = './configs/' + str(tLer) + '.cfg'
with open(pOutputFile, "w+") as opHandle:
#print('Writing configuration for {}'.format(tLer))
opHandle.write(lerConfig)
opHandle.write('\n')
使用一些 print() 语句我可以看到,使用基数 class object 创建组的代码添加了一个组,但迭代代码似乎添加或看到了一个名为“默认”的额外组。 'default' 是组的基础 class 中使用的名称。 一旦 object 被实例化,它就会被分配一个正确的组名。
Creating vrf bgp group object for xxx4-bb-pe1 BLUE: AS65YYY-BLUE-V4-PEER
Double checking bgp groups: 1
Creating vrf bgp group object for yyy6-bb-pe1 RED: AS65YYY-RED-V4-PEER
Double checking bgp groups: 1
Creating vrf bgp group object for zzz2-bb-pe1 BLUE: AS4200XXXXXX-BLUE-V4-PEER
Double checking bgp groups: 1
Creating vrf bgp group object for zzz2-bb-pe2 RED: AS4200XXXXXX-RED-V4-PEER
Double checking bgp groups: 1
Creating vrf bgp group object for xyxy2-bb-gw1 BLUE: AS4200XXXXXX-BLUE-V4-PEER
Double checking bgp groups: 1
Creating vrf bgp group object for xyxy2-bb-gw2 RED: AS4200XXXXXX-RED-V4-PEER
Double checking bgp groups: 1
Writing configuration for xxx4-bb-pe1
AS65YYY-BLUE-V4-PEER
Writing configuration for yyy6-bb-pe1
AS65YYY-RED-V4-PEER
Writing configuration for zzz2-bb-pe1
AS4200XXXXXX-BLUE-V4-PEER
Writing configuration for zzz2-bb-pe2
AS4200XXXXXX-RED-V4-PEER
Writing configuration for xyxy2-bb-gw1
What VRF: BLUE How many BGP Groups: 2 <<< extra group
AS4200XXXXXX-BLUE-V4-PEER
default << extra group
Writing configuration for xyxy2-bb-gw2
What VRF: RED How many BGP Groups: 2 <<< extra group
AS4200XXXXXX-RED-V4-PEER
default <<<< extra group
这是默认组 class 定义
class bgpGroup():
def __init__(self):
self.vrf = ''
self.grpName = 'default'
self.grpType = 'internal'
self.grpDescr = ''
self.grpLocalAddr = '0.0.0.0'
self.clusterid = ''
self.gr_disable = False
self.remove_private = False
self.as_override = False
self.peer_as = ''
self.local_as = ''
self.local_as_private = False
self.local_as_noprepend = False
self.holdtime = ''
self.grpFamily = []
self.grpImport = ''
self.grpExport = ''
self.grpNbrList = defaultdict(bgpNbr)
self.grpLoopDetect = False
self.grpMltHopTtl = 0
self.grpInetAsPathPrependReceive = False
self.grpLabelInet6AsPathPrependReceive = False
def __repr__(self):
return self.grpName
我真的不知道这个错误是什么,但你有没有试过:
for aKey in list(config.lerDevList[tLer].vrfs.keys())
这会在开始时从字典中获取所有键,如果添加了另一个条目,则无关紧要。
也不要说您不需要.keys()
,尽管它不会造成伤害。 遍历字典就是遍历它的键。
问题出在 jinja2 模板代码中。 在 for 循环的语句中引用了错误的变量。 修复它修复了错误。 对不起噪音。 错误确实指向 jinja2 代码,循环行的开头有错误。 没有指向有错误的实际行。 现在一切都好。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.