5

我在 python 中使用with statementPEP 343)在上下文之后自动管理资源清理时遇到了一些问题。特别是,with statement总是假定资源清理方法是.close(). 以下代码块中的 IE 会在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没有提供自定义要调用的清理方法名称的方法,如下所示

 def __exit__(self, *exc_info):
      self.thing.close()

但是,我确实注意到有一个参数exec_info,但没有在该特定方法中使用。有人知道为什么吗?

更大的问题是,如标题所示,如果可能的话,如何让 self.thing 调用任意清理方法?如果没有,最好的解决方法是什么?我应该回退使用try...finally吗?

4

2 回答 2

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]

于 2013-09-13T20:05:33.590 回答
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()调用当前实例的方法quit(),因此它将适用于所有驱动程序。(第一个只是修补 Firefox 驱动程序。)这lambda是必要的,因为quit()基类上的方法在许多(全部?)驱动程序上被覆盖,所以指向closequit类将调用基类的方法,而不是 on实际使用的类。

无论哪种方式,该类现在都非常适合与closing()with语句一起使用。

于 2013-09-13T21:42:45.840 回答