Today was a happy day: for the first time in my life I consciously used a python context manager. When I started coding with Python in May this year, I struggled to get the idea of context managers. Then I read a book “Python Tricks” by Dan Bader, which brought me out of darkness. Since then I was waiting for some real-life situation where I can apply my new knowledge. And today it happened!

So today I was writing a web scraper that supposed to get some information from the site X. Before scraping I needed to login: fill in a form and submit it, that is why I decided to use Selenium Webdriver. My first impulse was to write something like this:

driver = webdriver.Chrome()
try:
    driver.get('http://www.natalyakosenko.com/')

    email = driver.find_element_by_name('email')
    password = driver.find_element_by_name('password')

    email.send_keys('my_email')
    password.send_keys('my_password')
    driver.find_element_by_name('submit').click()
finally:
    driver.close()

Basically, this code creates an instance of Chrome webdriver, then tries to do some stuff (in this case fills in email/password and presses Submit button), and finally close method is called to close a browser.

Then I realised that I will need to use Selenium Webdirver in other parts of my code, and I did not want to instantiate driver and write try/catch again and again. And this is where I thought: what a great opportunity to try a with statement in action!

The previous code written using with statement:

class SeleniumDriver:
    def __enter__(self):
        self.driver = webdriver.Chrome()
        return self.driver

    def __exit__(self, exc_type, exc_val, exc_tb):
        if self.driver:
            self.driver.close()


with SeleniumDriver() as driver:
    driver.get('http://www.natalyakosenko.com/')

    email = driver.find_element_by_name('email')
    password = driver.find_element_by_name('password')

    email.send_keys('my_email')
    password.send_keys('my_password')
    driver.find_element_by_name('submit').click()

What is the benefit, you might think, instead of 12 lines of code got 19. But I do not need to define SeleniumDriver class every time. Whenever I need to use Selenium Webdriver in other parts of the code, I can simply write this:

with SeleniumDriver() as driver:
    driver.get('http://www.natalyakosenko.com/')

    email = driver.find_element_by_name('email')
    password = driver.find_element_by_name('password')

    email.send_keys('my_email')
    password.send_keys('my_password')
    driver.find_element_by_name('submit').click()

Isn’t it beautiful?