When I run this code, one of the selenium windows is not closed
import multiprocessing
from selenium import webdriver
class Worker:
def __init__(self):
self.driver = webdriver.Chrome()
def run(self):
self.driver.get('https://www.google.com')
processes = []
for i in range(2):
worker = Worker()
process = multiprocessing.Process(target=worker.run)
process.start()
processes.append(process)
for any_name in processes:
any_name.terminate()
But if I change variable name from any_name
to worker
, then all selenium windows are closed. Why is this happening?
PS version: python 3.7, chromedriver 83, selenium 3.141.0
This is because the browser closing behavior depends on the __del__
method of selenium.webdriver.common.service.Service
to make the browser Windows exit, and __del__
will only be called when there are no more references to your WebDriver
instances. Here is the implementation of Service.__del__
:
def __del__(self):
# `subprocess.Popen` doesn't send signal on `__del__`;
# so we attempt to close the launched process when `__del__`
# is triggered.
try:
self.stop()
except Exception:
pass
The stop()
method shuts everything down.
Now, the reason the variable naming matters is that it effects whether or not there are any references to a WebDriver
when your program exits. When your first for loop completes, worker
is still in-scope, which holds a reference to the second Worker
you created, which holds a reference to the WebDriver
. That keeps it in scope when your main program completes, which means __del__
is never called, and the browser window doesn't close.
However, when you re-use worker
for the second for loop, it means the reference to the second Worker
is no longer held, which means there are no references to WebDriver
in-memory, which means __del__
will be called and the window will close. You can confirm this behavior by explicitly adding worker = None
outside of the first for loop. With that change, both browser windows always exit, no matter what variable name you use in the second loop.