繁体   English   中英

RuntimeError dictionary changed size during iteration during 字典迭代

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM