Python运行时与VSCode调试模式下NoSuchElementException异常行为差异排查
环境信息
- Python 3.10.5
- Selenium 4.3.0
- Seleniumwire 4.6.5
- geckodriver 0.31.0
- Firefox 91.11.0esr (64-bit)
- IDE VSCode 1.70.1
需求与问题
我需要从维基百科超链接的悬停预览中提取图片链接和段落文本,但代码在Python直接运行和VSCode内置调试器中的表现不一致:
- 调试模式下代码符合预期,能正确捕获无图片预览场景的
NoSuchElementException异常; - 直接运行代码时,本该触发异常的无图片项(比如"Rassestandard")没被捕获,反而生成字典并加入结果列表,之后才进入
except块打印错误信息。
代码片段
def get_breed(a, driver, action): url = unquote(a.get_attribute("href")) if page_exist(url): scroll_shim(driver, a) action.move_to_element(a).perform() div_popup = driver.find_element(By.CLASS_NAME, "mwe-popups-container") if div_popup: try: img = div_popup.find_element(By.CLASS_NAME, "mwe-popups-thumbnail") p = div_popup.find_element(By.TAG_NAME, "p") print("test-1") except NoSuchElementException: print("test-4") print(err) return print("test-2") breed = { "name": a.text, "img": unquote(img.get_attribute("src")), "desc": p.text } return breed
def get_breeds_from_ul(breeds_url): driver = get_driver(breeds_url) action = ActionChains(driver) uls = driver.find_elements(By.XPATH, "//div[@class='mw-parser-output']/ul") breeds = [] for ul_tag in uls[:-2]: all_a = ul_tag.find_elements(By.TAG_NAME, "a") for a in all_a: breed = get_breed(a, driver, action) if breed: breeds.append(breed) print(breed) print("test-3") driver.close() return breeds
预期结果
无图片的预览项应该被跳过,不会生成字典并加入结果列表,输出示例如下:
$ python get_animals.py test-1 test-2 {'name': 'Bayerische Landgans', 'img': 'https://upload.wikimedia.org/wikipedia/commons/thumb/8/8b/Bayerische_Landgans.jpg/319px-Bayerische_Landgans.jpg', 'desc': 'Bayerische Landgänse sind Hausgänse, die in Franken, der Oberpfalz, Niederbayern und Schwaben gezüchtet wurden. „Bayerische Landgans“ ist ein Oberbegriff für die in diesen Regionen beheimateten Landschläge.'} test-3 test-1 test-4 test-1 test-2 {'name': 'Another animal name', 'img': 'another link', 'desc': 'Another description.'} test-3
疑问
为什么Python直接运行时会出现异常捕获延迟、逻辑执行顺序混乱的情况?是我在代码逻辑或异常处理上有错误吗?
问题分析与解决
核心问题点
- 时序不匹配:调试模式下代码逐行执行,悬停后的弹窗有足够时间渲染完成;直接运行时代码执行速度快,弹窗内部元素还没加载就开始查找,导致后续逻辑混乱——比如暂时找不到元素但后续又加载出来,异常捕获逻辑失效。
- 异常处理错误:
except块中引用了未定义的err变量,会触发新的NameError,干扰原异常的捕获流程,导致代码执行顺序错乱。 - 无效判断冗余:
div_popup = driver.find_element(...)如果找不到元素会直接抛出异常,后面的if div_popup:完全多余,因为查找成功后div_popup必然是非空对象。
修复方案
- 添加显式等待:对弹窗及内部元素使用显式等待,确保元素加载完成后再操作,解决时序问题。
- 修正异常处理:要么移除未定义的
err,要么正确捕获异常对象(except NoSuchElementException as err:)。 - 清理无效代码:删除多余的
if div_popup:判断。
修复后的get_breed函数示例:
from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC def get_breed(a, driver, action): url = unquote(a.get_attribute("href")) if page_exist(url): scroll_shim(driver, a) action.move_to_element(a).perform() # 等待弹窗容器加载 try: div_popup = WebDriverWait(driver, 5).until( EC.presence_of_element_located((By.CLASS_NAME, "mwe-popups-container")) ) except: return try: # 等待图片和段落元素加载完成 img = WebDriverWait(div_popup, 3).until( EC.presence_of_element_located((By.CLASS_NAME, "mwe-popups-thumbnail")) ) p = WebDriverWait(div_popup, 3).until( EC.presence_of_element_located((By.TAG_NAME, "p")) ) print("test-1") except NoSuchElementException as err: print("test-4") print(err) return print("test-2") breed = { "name": a.text, "img": unquote(img.get_attribute("src")), "desc": p.text } return breed
补充说明
调试模式的逐行执行给了弹窗足够的加载时间,所以异常能被正确捕获;直接运行时速度快,元素加载不及时就会导致逻辑出错,显式等待是解决这类Selenium时序问题的标准方案。
内容的提问来源于stack exchange,提问作者Angry Daddy
相关产品推荐
相关产品推荐

