Home > Net >  Python selenium child class opens a new browser window - how to prevent this?
Python selenium child class opens a new browser window - how to prevent this?

Time:02-05

I am trying to create a child class for my selenium browser. Here is my code:

class SeleniumDriver:
    """Class that represents a game."""
    def __init__(self):
        # start Tor browser
        self.profile_path = r'C:\Tor Browser2\Browser\TorBrowser\Data\Browser\profile.default'
        self.options = Options()
        self.options.binary_location = r'C:\Tor Browser2\Browser\firefox.exe'
        self.options.set_preference('profile', self.profile_path)
        self.service = Service('C:/Utility/BrowserDrivers/geckodriver/geckodriver.exe')
        self.driver = Firefox(service=self.service, options=self.options)

class Items(SeleniumDriver):
    def __init__(self):
        super().__init__()
    # More methods that do stuff....

When I initialize both classes, the child class starts a new browser window. How can I make it attach to existing/parent initialized browser? I tried separating "self.driver = Firefox" to another method, but then child class throws:

AttributeError: 'Item' object has no attribute 'driver'

CodePudding user response:

There are multiple ways to resolve this.

But generally, you should think do you really need inheritance?

Why not Delegation?

If you just want to use the driver, launched by some class, then add driver as an argument to the constructor, or even add SeleniumDriver as an argument.

See https://erikscode.space/index.php/2020/08/01/delegate-and-decorate-in-python-part-1-the-delegation-pattern/

With driver as an argument

class SeleniumDriver:

    driver = None

    def __init__(self):
        ...
        self.driver = Firefox(service=self.service, options=self.options)

class Items:

    driver = None

    # parameterized constructor
    def __init__(self, driver):
        self.driver = driver

...
seleniumDriver = SeleniumDriver()
itemsObj = Items(seleniumDriver.driver)

With SeleniumDriver as argument

class Items:

    seleniumDriver = None

    # parameterized constructor
    def __init__(self, seleniumDriver):
        self.seleniumDriver = seleniumDriver

...

seleniumDriver = SeleniumDriver()
itemsObj = Items(seleniumDriver)

Stay using inheritance

For this case, I suggest moving out this line from the constructor

self.driver = Firefox(service=self.service, options=self.options)

to the separate start_driver method:

class SeleniumDriver:
    
    def __init__(self):
        self.profile_path = r'C:\Tor Browser2\Browser\TorBrowser\Data\Browser\profile.default'
        self.options = Options()
        self.options.binary_location = r'C:\Tor Browser2\Browser\firefox.exe'
        self.options.set_preference('profile', self.profile_path)
        self.service = Service('C:/Utility/BrowserDrivers/geckodriver/geckodriver.exe')

    def start_driver(self):
        self.driver = Firefox(service=self.service, options=self.options)


class Items(SeleniumDriver):
    def __init__(self):
        super().__init__()

    def with_driver(self, driver):
        self.driver = driver

...
seleniumDriver = SeleniumDriver()
seleniumDriver.start_driver()

itemsObj = Items()
itemsObj.with_driver(seleniumDriver.driver)

or add driver arg to constructor:

class Items(SeleniumDriver):
    def __init__(self, driver):
        super().__init__()
        self.driver = driver

...
seleniumDriver = SeleniumDriver()
seleniumDriver.start_driver()
itemsObj = Items(seleniumDriver.driver) #make sure start_driver() already invoked on seleniumDriver
  •  Tags:  
  • Related