我在python中使用with statement
(PEP 343)遇到了一些问题,以便在上下文后自动管理资源清理。特别是,with statement
始终假定资源清理方法为.close()
。 I.E.在下面的代码块中,browser.close()
在执行超出上下文时自动被调用,但是,browser.close()
不是正确的清理,因为它只关闭当前窗口而不是整个浏览器。它应该做的是致电browser.quit()
。
with contextlib.closing(webdriver.Firefox()) as browser:
# do something with browser
# at this point browser.close() has been called.
不幸的是,contextlib.closing
没有提供一种方法来自定义要调用的清理方法名称,如明显所见here:
def __exit__(self, *exc_info):
self.thing.close()
但是,我注意到有一个参数exec_info
,但没有在该特定方法中使用。谁知道为什么?
更大的问题是,如标题所示,如果可能的话,如何使用self.thing来调用任意清理方法?如果没有,最好的解决方法是什么?我应该退回使用try...finally
吗?
答案 0 :(得分:9)
嗯,这是python,您可以根据closing
创建自己的contextlib.closing
课程并覆盖__exit__()
方法:
import contextlib
from selenium import webdriver
class closing(contextlib.closing):
def __exit__(self, *exc_info):
self.thing.quit()
with closing(webdriver.Firefox()) as browser:
browser.get('http://stackoverflow.com')
仅供参考,有人建议将webdriver
作为上下文管理器,但由于won't fix
是关闭浏览器的正确方法,因此它已关闭quit()
,应该调用它明确地,请参阅Make webdriver a context manager [python bindings]。
答案 1 :(得分:4)
除了alecxe的答案,这是完全有效的,你也可以做这样的事情:
webdriver.Firefox.close = webdriver.Firefox.quit
现在close
方法存在且与quit
方法相同。
或者更好:
from selenium.webdriver.remote.webdriver import WebDriver as RemoteWebDriver
RemoteWebDriver.close = lambda self: self.quit()
这会修补基类以添加调用当前实例的close()
的{{1}}方法,因此它将适用于所有驱动程序。 (第一个只是修补Firefox驱动程序。)quit()
是必要的,因为基类上的lambda
方法在许多(所有?)驱动程序上被覆盖,因此将quit()
指向基类上的close
将调用基类的方法,而不是实际使用的类中的方法。
无论哪种方式,该类现在非常适合与quit
和closing()
语句一起使用。