My Python script uses Selenium to automate a browser on Windows. I want to be able to interrupt the script by pressing CTRL+C. But even if I catch the exception, the WebDriver terminates on the interrupt:
from selenium import webdriver
driver = webdriver.Chrome()
try:
while True:
pass
except KeyboardInterrupt:
print('KeyboardInterrupt caught')
driver.get('https://www.google.com') # will fail
When CTRL+C is pressed, the WebDriver window closes immediately. Any subsequent calls to driver methods raise a urllib3 exception.
If I am using WebDriver in Python REPL and I need to terminate some function via interrupt, I don't want that to destroy my driver instance. Similarly when testing a longer automated process, I would like to be able to cancel execution manually if something goes awry but allow the browser window to remain open for debugging.
I could use an instance of Remote WebDriver (via Selenium Grid) on my local machine as suggested here but I do not want to add complexity with managing the grid. The solutions mentioned here seem to only work on Unix.
Is there a simple way to achieve this on Windows?
The WebDriver terminates because in Windows the CTRL+C press, which interrupts execution (Windows doesn't have "signals") is propagated to child processes. Selenium's WebDriver is a separate process (created by subprocess.Popen
) which the program communicates with over HTTP.
It is possible to instantiate a Selenium Service object using a flag so it creates the WebDriver subprocess in a separate process group:
from selenium import webdriver
from selenium.webdriver.chrome.service import Service
import subprocess
serv = Service(popen_kw={"creation_flags": subprocess.CREATE_NEW_PROCESS_GROUP})
driver = webdriver.Chrome(service = serv)
Now the driver will not receive any "signals" from the parent process!