5

with statementPython で( PEP 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

Well, it's python, you can make your own closing class, based on contextlib.closing and override __exit__() method:

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')

FYI, there was a proposal to make webdriver a context manager, but it was closed as won't fix since quit() is the right way to close the browser, and it should be called explicitly, see 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実際に使用されているクラス。

closing()いずれにせよ、このクラスはおよびwithステートメントでの使用に完全に適しています。

于 2013-09-13T21:42:45.840 に答える