如何用while循环移除列表元素?网页测试代码执行异常求助
问题分析与解决方案
首先,我先梳理下你的核心需求:你需要循环打开网页获取版本标识(p1/p2),只要该标识在cluster1列表中,就执行测试函数并将其从列表中移除,直到cluster1为空;但注释掉cluster1.remove(new[-1])时会错误触发else分支,同时当前代码还存在一些逻辑漏洞需要修正。
问题根源
- 循环内未重新获取版本值:你的代码只在
login1()开头获取了一次new值,进入while循环后没有再次打开网页获取新的版本标识,导致每次判断的都是同一个new[-1]。如果这个值已经被移除出cluster1,就会直接触发else分支退出循环。 - 直接修改列表的潜在误解:你提到迭代列表时不能直接移除元素,但你的循环是基于列表长度而非迭代列表本身,所以直接移除是可行的——真正的问题出在没有动态更新版本值上。
修正后的完整代码
我重新调整了代码结构,把版本获取逻辑封装成函数,确保每次循环都能重新获取最新的版本值,同时优化了循环逻辑:
from selenium import webdriver import unicodedata import time new_ver_names = [] cluster1 = ['p1', 'p2'] def get_portal_version(): # 初始化浏览器、登录并获取版本的封装函数 ChromeDriver = 'C:\\PortalTesting\\Drivers\\chromedriver.exe' chrome_options = webdriver.ChromeOptions() chrome_options.add_argument('--no-sandbox') chrome_options.add_argument("--incognito") chrome_options.add_argument("--window-size=1920x1080") driver = webdriver.Chrome(executable_path=ChromeDriver, options=chrome_options) driver.maximize_window() driver.implicitly_wait(130) try: driver.get("MY_URL") print("session id ", driver.session_id) # 登录操作 username = driver.find_element_by_css_selector("#uid") username.send_keys("username") password = driver.find_element_by_css_selector("#pid") password.send_keys("password") login_button = driver.find_element_by_class_name("secondarybtnlabel") login_button.click() # 提取并处理版本值 dc_elm = driver.find_element_by_xpath('/html/body/div[4]/div/div[2]/span[2]').text new = unicodedata.normalize('NFKD', dc_elm).encode('ascii', 'ignore').split() portal_version = new[-1] print("Portal version: ", portal_version) # 登出与清理 logout_btn = driver.find_element_by_xpath('/html/body/div[4]/div[2]/div/div[4]/div/div[2]/div/header/div[2]/table/tbody/tr/td[3]/div/li') logout_btn.click() driver.delete_all_cookies() print("Clearing cookies") time.sleep(3) return portal_version, driver except Exception as e: print(f"获取版本时出错: {e}") driver.quit() return None, None def test1(): # 替换成你的test1实际逻辑 print("执行test1...") def test2(): # 替换成你的test2实际逻辑 print("执行test2...") # 主循环:直到cluster1为空 while cluster1: print("cluster1当前长度(循环前):", len(cluster1)) # 每次循环重新获取版本和浏览器实例 portal_version, driver = get_portal_version() if not portal_version or not driver: print("获取版本失败,退出循环") break if portal_version in cluster1: print(f"{portal_version} 在cluster1中,执行测试") test1() test2() new_ver_names.append(portal_version) cluster1.remove(portal_version) print("cluster1当前长度(循环后):", len(cluster1)) driver.quit() else: print(f"{portal_version} 不在cluster1列表中") driver.quit() # 如果不需要退出循环,可注释掉下面的break,继续尝试获取新值 # break print("所有测试执行完成!")
关键优化点说明
- 封装版本获取逻辑:把登录、获取版本、登出的代码封装成独立函数,确保每次循环都能重新打开网页获取最新的版本标识,彻底解决旧值重复判断的问题。
- 优化循环条件:用
while cluster1:替代while len(cluster1) !=0,更符合Python的简洁编码风格,可读性更强。 - 独立浏览器实例:每次获取版本后关闭当前浏览器,下次循环重新创建,避免会话冲突或状态残留。
- 异常处理:添加异常捕获,防止网页加载失败、元素找不到等情况导致程序直接崩溃。
- 列表移除的安全性:你的循环是基于列表是否为空,而非迭代列表元素,所以直接使用
cluster1.remove(portal_version)是完全安全的。如果后续cluster1元素较多,建议改用集合(set(['p1','p2'])),集合的in判断和移除操作效率更高。
关于你尝试的列表推导式
你之前的列表推导式逻辑不符合需求,因为它只是固定循环len(cluster1)次,没有关联每次动态获取的网页版本值。列表推导式更适合批量处理已知静态数据,而这里需要动态获取外部网页的动态数据,所以while循环是更合适的选择。
内容的提问来源于stack exchange,提问作者PRK
相关产品推荐
相关产品推荐

