嵌套的 for 循环仅执行一次

问题描述 投票:0回答:2

我正在编写一个简单的 Python:Pexpect 脚本,它是旧的 TCL:Expect 工作脚本的替代品,我用来将配置更改或命令推送到我们的网络交换机。

如果我写:

h_ls = open(hostls,"r")
c_ls = open(commands,"r")
for host in h_ls:
  host = host.strip()
  try:
    s = pxssh.pxssh(timeout=5,logfile = sys.stdout,options={
                "StrictHostKeyChecking": "no",
                "UserKnownHostsFile": "/dev/null",
                "AddKeysToAgent": "yes"},encoding='utf-8')
    s.login (host, user, password,\
            auto_prompt_reset=False,\
            original_prompt=r'.*#')
    print (">>>>> Working on "+host+" @ "+str(now)+" <<<<<\n")
    s.prompt()
    for cmd in c_ls:
     s.sendline(cmd+"\n")
     s.prompt()
     print(s.before)
    s.logout()
  except pxssh.ExceptionPxssh as e:
    print("***pxssh failed on login***")
    #traceback.print_exc()
    print("***"+str(e)+" "+host+"***")

“commands”变量中包含的命令仅在列表“hostls”的第一个主机中执行一次

如果我写:

h_ls = open(hostls,"r")
for host in h_ls:
  host = host.strip()
  try:
    s = pxssh.pxssh(timeout=5,logfile = sys.stdout,options={
                "StrictHostKeyChecking": "no",
                "UserKnownHostsFile": "/dev/null",
                "AddKeysToAgent": "yes"},encoding='utf-8')
    s.login (host, user, password,\
            auto_prompt_reset=False,\
            original_prompt=r'.*#')
    print (">>>>> Working on "+host+" @ "+str(now)+" <<<<<\n")
    s.prompt()
    c_ls = open(commands,"r")
    for cmd in c_ls:
     s.sendline(cmd+"\n")
     s.prompt()
     print(s.before)
    s.logout()
  except pxssh.ExceptionPxssh as e:
    print("***pxssh failed on login***")
    #traceback.print_exc()
    print("***"+str(e)+" "+host+"***")

“hostls”变量的每个主机都正确执行命令。 我不明白什么?

为了完整起见,在这个脚本的 Tcl:Expect 兄弟中,我的逻辑与第一个示例的逻辑类似,并且它工作正常,所以我可能遗漏了一些关于 Python 的知识。这与块“try except”的管理方式有关吗?我搜索了相关信息,但没有发现任何关于这个特定论点有意义的内容。

python for-loop pexpect
2个回答
1
投票

这与错误处理无关。注意

c_ls
的范围 - 在第一个示例中,您在循环之外打开文件,因此对象被创建一次,当您迭代它时,它会在第一次迭代后耗尽,不再执行任何命令对于其余的主机。然而,在第二段代码中,您将在该循环内打开文件,这意味着为每个主机创建一个新的
c_ls
对象,因此它包含要迭代的所有命令。


1
投票

open() 函数返回一个文件对象,可用于迭代文件中的行。不过,您只能迭代它们一次。在外循环的第一次迭代中,您将迭代它们,耗尽迭代器。从第二次迭代开始,没有元素剩余。

解决方案:要么在外循环的每次迭代中重新打开文件(您在第二个代码示例中所做的),要么更好地将命令存储在列表中,该列表可以一次又一次地迭代:

with open(commands, "r") as f:
    c_ls = f.readlines()

(使用“with”可以确保即使在出现异常的情况下也能正确关闭文件)

编辑: f.readlines() 比 list(f) 更清晰。

© www.soinside.com 2019 - 2024. All rights reserved.