Selenium leaves behind running processes?
As already pointed out you should run browser.quit()
But on linux (inside docker) this will leave defunct processes. These are typically not really a problem as they are mere an entry in the process-table and consume no resources. But if you have many of those you will run out of processes. Typically my server melts down at 65k processes.
It looks like this:
# root@dockerhost1:~/odi/docker/bf1# ps -ef | grep -i defunct | wc -l
28599
root@dockerhost1:~/odi/docker/bf1# ps -ef | grep -i defunct | tail
root 32757 10839 0 Oct18 ? 00:00:00 [chrome] <defunct>
root 32758 895 0 Oct18 ? 00:00:02 [chrome] <defunct>
root 32759 15393 0 Oct18 ? 00:00:00 [chrome] <defunct>
root 32760 13849 0 01:23 ? 00:00:00 [chrome] <defunct>
root 32761 472 0 Oct18 ? 00:00:00 [chrome] <defunct>
root 32762 19360 0 01:35 ? 00:00:00 [chrome] <defunct>
root 32763 30701 0 00:34 ? 00:00:00 [chrome] <defunct>
root 32764 17556 0 Oct18 ? 00:00:00 [chrome] <defunct>
root 32766 8102 0 00:49 ? 00:00:00 [cat] <defunct>
root 32767 9490 0 Oct18 ? 00:00:00 [chrome] <defunct>
The following code will solve the problem:
def quit_driver_and_reap_children(driver):
log.debug('Quitting session: %s' % driver.session_id)
driver.quit()
try:
pid = True
while pid:
pid = os.waitpid(-1, os.WNOHANG)
log.debug("Reaped child: %s" % str(pid))
#Wonka's Solution to avoid infinite loop cause pid value -> (0, 0)
try:
if pid[0] == 0:
pid = False
except:
pass
#---- ----
except ChildProcessError:
pass
Whats happening is that your code is throwing an exception, halting the python process from continuing on. As such, the close/quit methods never get called on the browser object, so the chromedrivers just hang out indefinitely.
You need to use a try/except block to ensure the close method is called every time, even when an exception is thrown. A very simplistic example is:
from selenium import webdriver
browser = webdriver.Chrome("path/to/chromedriver")
try:
browser.get("http://stackoverflow.com")
browser.find_element_by_id('...').click()
except:
browser.close()
browser.quit() # I exclusively use quit
There are a number of much more sophisticated approaches you can take here, such as creating a context manager to use with the with
statement, but its difficult to recommend one without having a better understanding of your codebase.