这是我的生产程序的修改版本,非常简单,我在其中复制了遇到的错误。我的程序应该加载IP地址列表(用于路由器),并通过发送命令和收集返回信息来使用它们。该列表加载了所有IP,但是我的程序逻辑应跳过那些不在线的IP(online
变量为False
),也就是说,命令不应在那些离线的路由器中运行。
Class Router
代表IP列表中的每个路由器。它具有3个对象级变量:addr
代表路由器地址,online
代表在线状态(True
或False
),而infoBasic
代表信息的字典,例如{'Name': 'router name', 'Uptime': 'time router is up', 'OS': 'IOS version'}
,依此类推。对于不在线的路由器,此字典应为空({}
)。主程序将永远不会与此类交互,因为它由下一个类(RouterList
)实例化
class RouterList
代表所有Router
对象的列表,这是具有与main
进行交互的方法的列表。最初,它将IP地址列表加载到routerList
变量中,然后实例化每个路由器,并将IP地址作为密钥,并将Router对象作为值保存到dict routerDict
中。为了混淆,我手动将第二个IP设置为离线。
在RouterList
中,我的getName method
(以及所有其他方法)应该遍历routerDict
并运行命令以获取路由器名称并将该信息写入Router
对象,在dict变量infoBasic
中。在这种情况下,getName
调用getBasic
并传递Router
对象,该对象调用Router
对象runComm
方法并传递字符串"sh version"
。在这里,不要介意愚蠢的逻辑,在我的实际生产程序中,我正在使用缓存装饰器仅运行一次命令并将其存储以备后用。
在循环内的同一getName
方法中,它应跳过离线路由器。在程序结尾,我调用getRouters
,它应该只打印routerList
的字典及其内部信息。它不仅填充了处于脱机状态的路由器中的信息,而且还在所有路由器对象中复制了相同的信息(更具体地说,看起来它对dict的所有项目都应用了相同的内容,因此最后一个是在末尾重叠)。
这是我的完整程序:
class Router:
addr = None
online = False
infoBasic = {}
def __init__(self, addr = None):
self.addr = addr
if self.addr == '192.168.10.50':
self.online = False
else:
self.online = True
def runComm(self, command = None):
if command == None:
return "Error"
return "Return of command for router {}".format(self.addr)
class RouterList:
routerList = None
routerDict = {}
def __init__(self, routerList = None):
if routerList == None:
self.routerList = ['192.168.10.10', '192.168.10.50', '192.168.10.100']
else:
self.routerList = routerList
for routerAddr in self.routerList:
router = Router(routerAddr)
self.routerDict[routerAddr] = router
print("Router list loaded")
def getRouters(self):
""" Return list of routers """
for router in self.routerDict.values():
# print below should show the 3 routers but only .10 and .100 with infoBasic populated
print(router.addr + ', online = ' + str(router.online) + ' - ' + str(router.infoBasic))
def getBasic(self, *args, **kwargs):
""" Call router runComm method and return show version output """
return args[0].runComm("sh version")
def getName(self):
""" Call router runComm method and return show version output """
for router in self.routerDict.values():
if router.online == True:
print('Setting name for ' + router.addr)
# below I tried to use the self dict to write the return of getBasic
self.routerDict[router.addr].infoBasic['Name'] = self.getBasic(router)
def getUptime(self):
""" Return router uptime """
for router in self.routerDict.values():
if router.online == True:
# below I tried to use the router variable from the for loop to write the return of getBasic
router.infoBasic['Uptime'] = self.getBasic(router)
if __name__ == '__main__':
rl = RouterList()
rl.getName()
rl.getUptime()
rl.getRouters()
这是输出:
# python3 simulate-error.py
Router list loaded
Setting name for 192.168.10.10
Setting name for 192.168.10.100
192.168.10.10, online = True - {'Name': 'Return of command for router 192.168.10.100', 'Uptime': 'Return of command for router 192.168.10.100'}
192.168.10.50, online = False - {'Name': 'Return of command for router 192.168.10.100', 'Uptime': 'Return of command for router 192.168.10.100'}
192.168.10.100, online = True - {'Name': 'Return of command for router 192.168.10.100', 'Uptime': 'Return of command for router 192.168.10.100'}
如您所见,在“设置名称为...”区域中,看起来确实已跳过了脱机的路由器。但是最后,所有路由器最终都获得了相同的信息。我知道我可能忽略了一些真正愚蠢而显而易见的内容,但是无论我复查多少次,我都找不到。你能帮忙吗?