Python Selenium中同一ProgressBar对象element属性表现异常求助
最近在用Python的Selenium批量定位页面上的ProgressBar时,碰到了个让人摸不着头脑的问题——明明是指向同一个对象的两个引用,表现却天差地别。先给你看看我在pdb里的调试记录:
(Pdb) ml.colorbars[2] <framework.web.base.element.ProgressBar object at 0x250dc50> (Pdb) ml.colorbars[2].element #### 此处无返回内容 (Pdb) ml.colorbar_2 <framework.web.base.element.ProgressBar object at 0x250dc50> (Pdb) ml.colorbar_2.element <selenium.webdriver.firefox.webelement.FirefoxWebElement (session="b2dd0af2-53fb-49fd-8595-6cd50c751f99", element="6a49815e-0188-483e-b451-41ed88f916a0")> (Pdb) ml.colorbars[2] <framework.web.base.element.ProgressBar object at 0x250dc50> (Pdb) ml.colorbars[2].element <selenium.webdriver.firefox.webelement.FirefoxWebElement (session="b2dd0af2-53fb-49fd-8595-6cd50c751f99", element="6a49815e-0188-483e-b451-41ed88f916a0")>
这里colorbar_2是我单独命名的ProgressBar变量,colorbars[2]是存储所有进度条的列表里的第三个元素——你看它们的内存地址完全一致,说明指向的是同一个对象。但一开始调用colorbars[2].element时啥都没返回,直到我调用了colorbar_2.element之后,colorbars[2].element才正常输出了WebElement对象。
附上相关的实例化代码:
namespace = locals() colorbars = [] loc_template = "tr[{}]//div[@class='elWidgets-ProgressBar-bar']" # colorbars实例化 for index in range(bar_num): colorbar_locator = ('xpath', loc_template.format(index)) namespace['colorbar_%s' % index] = ProgressBar(colorbar_locator) colorbars.append( namespace['colorbar_%s' % index] )
问题根源分析
这种现象十有八九是因为你的ProgressBar类里的element属性用了**延迟加载(Lazy Loading)**机制——简单说就是,这个属性不会在实例化时就立刻去调用Selenium定位元素,而是要等到你第一次访问它的时候,才会执行定位逻辑并获取WebElement对象。
那为什么两个引用会有差异?其实本质是同一个对象的属性被触发加载的时机不同:
- 当你第一次访问
colorbar_2.element时,触发了这个实例的element属性加载逻辑,成功拿到了WebElement; - 因为
colorbars[2]和colorbar_2是同一个对象,所以之后再访问colorbars[2].element时,属性已经加载完成,自然就能返回对应的WebElement了。
而一开始colorbars[2].element没有返回内容,就是因为此时这个属性还没被触发加载,可能返回的是None或者还没执行定位逻辑,所以pdb里没有显示返回值。
解决思路
如果你想让列表里的所有ProgressBar实例在初始化时就完成element的加载,可以试试这两种方法:
- 修改
ProgressBar类的实现,让它在实例化时就主动获取element; - 在实例化循环里主动触发一次element属性的访问,比如加上一行:
namespace['colorbar_%s' % index].element
当然,如果你能接受延迟加载的机制,也完全没问题——只要确保在使用某个ProgressBar实例之前,至少通过任意一个引用访问过它的element属性就行。
内容的提问来源于stack exchange,提问作者xlinush

