Is it possible for contextlib.closing () to call an arbitrary cleanup method instead of .close ()

I am having problems using with statement ( PEP 343 ) in python to automatically control resource cleanup after context. In particular, with statement always assumes the .close() resource cleanup method. I.E. in the next block of code, browser.close() automatically called when execution ends out of context, however browser.close() not the correct cleanup, since it closes the current window, not the entire browser. What was supposed to do was call browser.quit() .

 with contextlib.closing(webdriver.Firefox()) as browser: # do something with browser # at this point browser.close() has been called. 

Unfortunately, contextlib.closing does not provide a way to customize the name of the cleanup method that should be called, as you can see here :

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

However, I notice that the exec_info argument exec_info , but was not used in this particular method. Does anyone know why?

The bigger the question, the better, as the name, if possible, how to have self.thing to call an arbitrary cleaning method? If not, what is the best way to work? Should I revert to using try...finally ?

+4
source share
2 answers

Well, this is python, you can create your own closing class based on contextlib.closing and override the __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 wasn’t closed as won't fix , since quit() is the right way to close the browser, and it must be called explicitly, see Make webdriver a context manager [python bindings] .

+9
source

In addition to alecxe's answer, which is completely plausible, you can also do something like this:

 webdriver.Firefox.close = webdriver.Firefox.quit 

Now there is a close method and the same as the quit method.

Or maybe better:

 from selenium.webdriver.remote.webdriver import WebDriver as RemoteWebDriver RemoteWebDriver.close = lambda self: self.quit() 

This fixes the base class to add a close() method that calls the current quit() instance, so it will work with all drivers. (The first simply fixes the Firefox driver.) lambda necessary because the quit() method in the base class is overridden on many (all?) Drivers, so pointing to quit based on the class will call the base class method, and not the one used on the class itself.

In any case, the class is now great for use with closing() and the with statement.

+4
source

Source: https://habr.com/ru/post/1502109/


All Articles