hide chromeDriver console in python
Asked Answered
E

8

15

I'm using chrome driver in Selenium to open chrome , log into a router, press some buttons ,upload configuration etc. all code is written in Python.

here is the part of the code to obtain the driver:

chrome_options = webdriver.ChromeOptions()
prefs = {"download.default_directory":  self.user_local}
chrome_options.add_experimental_option("prefs", prefs)
chrome_options.experimental_options.
driver = webdriver.Chrome("chromedriver.exe", chrome_options=chrome_options)
driver.set_window_position(0, 0)
driver.set_window_size(0, 0)

return driver

when i fire up my app, i get a chromedriver.exe console (a black window) followed by a chrome window opened and all my requests are done.

My question: is there a way in python to hide the console window ?

(as you can see i'm also re-sizing the chrome window ,my preference would be doing things in a way the user wont notice anything happening on screen)

thanks Sivan

Excess answered 29/11, 2015 at 14:23 Comment(1)
Could you find a way to hide the console window ?Hanging
M
32

You will have to edit Selenium Source code to achieve this. I am a noob too, and I dont fully understand the overall consequences of editing source code but here is what I did to achieve hiding the webdriver console window on Windows 7, Python 2.7.

Locate and edit this file as follows: located at Lib\site-packages\selenium\webdriver\common\service.py in your Python folder.

Edit the Start() function by adding the creation flags this way: creationflags=CREATE_NO_WINDOW

The edited method will be as below:

def start(self):
    """
    Starts the Service.

    :Exceptions:
     - WebDriverException : Raised either when it can't start the service
       or when it can't connect to the service
    """
    try:
        cmd = [self.path]
        cmd.extend(self.command_line_args())
        self.process = subprocess.Popen(cmd, env=self.env,
                                        close_fds=platform.system() != 'Windows',
                                        stdout=self.log_file, stderr=self.log_file, creationflags=CREATE_NO_WINDOW)
    except TypeError:
        raise

You will have to add the relevant imports:

from win32process import CREATE_NO_WINDOW

This should also work for Chrome webdriver as they import the same file to start the webdriver process.

Metatarsus answered 8/10, 2016 at 21:15 Comment(9)
thanks! it works in windows 7 + python 2.7 + selenium (3.8). I used py2exe to pack my app.Intussuscept
Worth noting that CREATE_NO_WINDOW is just a constant, so you don't necessarily need pywin32. The value of the constant is 134217728 which should work the same.Privateer
The file name may be service.py instead of services.py as it was in my case. I used pyinstaller to package my app and this change worked to not display the chromedriver console window.Composed
You can also subclass the Selenium code and override just what you need. I have done this myself and I'll post some example code shortlyStockist
Hi, I am using windows 10, python 3.7 and selenium 3.14, I tried using the function, since I am on window 10 it gave me import error for from win32process import CREATE_NO_WINDOW. So, I used the constant 134217728 as suggested above. I had stdin = 'PIP', in my Popen args. I removed it. Now the script works fine when I run locally. But when I make .exe using pyinstaller, it does not run at all. Any solutions.Scrogan
@Udit Hari Vashisht try this it worked for me self.process = subprocess.Popen(cmd, stdin=PIPE, stdout=PIPE, stderr=PIPE, shell=False, creationflags=0x08000000)Hofer
This isnt woking for me as of 2020. Any ideas?Morphology
Nowadays it's not working for me. While from win32process import CREATE_NO_WINDOW got error. I used instead from subprocess import CREATE_NO_WINDOW but it's not hiding cmd in my app on other PC only on mineDerogate
@Metatarsus Please see my question if you would help. I asked this again because nothing from this page is not working for me or i have dead brainDerogate
F
20

New easy solution! (in selenium4)

I needed that too, so I implemented and commited this feature on GitHub as part of selenium4 release. We no longer need to edit the selenium library for this.

from selenium import webdriver
from selenium.webdriver.chrome.service import Service as ChromeService # Similar thing for firefox also!
from subprocess import CREATE_NO_WINDOW # This flag will only be available in windows

# Define your own service object with the `CREATE_NO_WINDOW ` flag
# If chromedriver.exe is not in PATH, then use:
# ChromeService('/path/to/chromedriver')
chrome_service = ChromeService('chromedriver')
# Use `chrome_service.creationflags` for selenium < 4.6
chrome_service.creation_flags = CREATE_NO_WINDOW

driver = webdriver.Chrome(service=chrome_service)

Now, command-prompt window does not open up. This is especially useful when you have a GUI desktop app which is responsible for opening selenium browser.

Also, note that we only need to do this in Windows.

Folkrock answered 12/2, 2022 at 15:10 Comment(10)
This does indeed work with Firefox as well. Not only is this the only solution that worked for me, this is also the cleanest.Yecies
This seems to be the best solution so far. Work for Edge driver also. Thanks.Lasley
@Ali Sajjad Please see my question if you would help. I asked this again because nothing from this page is not working for me or i have dead brainDerogate
@Derogate Alright I'll have a close look. Another thing you need to keep in mind is that you should run the PyQt5 app in windowed mode. Name your file prog.pyw.Folkrock
@AliSajjad I'm using pyinstaller --windowed parameterDerogate
Thanks, Buddy. Its works seamlesslyStertorous
@AliSajjad it doesn't work for me. Please read here. thanks #74462347Triumphal
At some point selenium changed creationflags to creation_flags. This solution worked for me after making this changeWolford
@Wolford Can you mention which version uses creation_flags for the first time? This will surely be helpful.Folkrock
@AliSajjad Note that Selenium has turned its Service.creationflags into Service.creation_flags since version 4.6.0.Wolford
S
14

There's a lot of questions relating to this and a lot of various answers. The issue is that using Selenium in a Python process without a console window of its own will cause it to launch its drivers (including the chromedriver) in a new window.

Rather than modifying the Selenium code directly (although this needs to be done eventually) one option you have is to create your own sub-classes for both the Chrome WebDriver and the Service class it uses. The Service class is where Selenium actually calls Popen to launch the service process, e.g. chromedriver.exe (as mentioned in the accepted answer):

import errno
import os
import platform
import subprocess
import sys
import time
import warnings

from selenium.common.exceptions import WebDriverException
from selenium.webdriver.common import utils
from selenium.webdriver.remote.webdriver import WebDriver as RemoteWebDriver
from selenium.webdriver.chrome import service, webdriver, remote_connection

class HiddenChromeService(service.Service):

    def start(self):
        try:
            cmd = [self.path]
            cmd.extend(self.command_line_args())

            if platform.system() == 'Windows':
                info = subprocess.STARTUPINFO()
                info.dwFlags = subprocess.STARTF_USESHOWWINDOW
                info.wShowWindow = 0  # SW_HIDE (6 == SW_MINIMIZE)
            else:
                info = None

            self.process = subprocess.Popen(
                cmd, env=self.env,
                close_fds=platform.system() != 'Windows',
                startupinfo=info,
                stdout=self.log_file,
                stderr=self.log_file,
                stdin=subprocess.PIPE)
        except TypeError:
            raise
        except OSError as err:
            if err.errno == errno.ENOENT:
                raise WebDriverException(
                    "'%s' executable needs to be in PATH. %s" % (
                        os.path.basename(self.path), self.start_error_message)
                )
            elif err.errno == errno.EACCES:
                raise WebDriverException(
                    "'%s' executable may have wrong permissions. %s" % (
                        os.path.basename(self.path), self.start_error_message)
                )
            else:
                raise
        except Exception as e:
            raise WebDriverException(
                "Executable %s must be in path. %s\n%s" % (
                    os.path.basename(self.path), self.start_error_message,
                    str(e)))
        count = 0
        while True:
            self.assert_process_still_running()
            if self.is_connectable():
                break
            count += 1
            time.sleep(1)
            if count == 30:
                raise WebDriverException("Can't connect to the Service %s" % (
                    self.path,))


class HiddenChromeWebDriver(webdriver.WebDriver):
    def __init__(self, executable_path="chromedriver", port=0,
                options=None, service_args=None,
                desired_capabilities=None, service_log_path=None,
                chrome_options=None, keep_alive=True):
        if chrome_options:
            warnings.warn('use options instead of chrome_options',
                        DeprecationWarning, stacklevel=2)
            options = chrome_options

        if options is None:
            # desired_capabilities stays as passed in
            if desired_capabilities is None:
                desired_capabilities = self.create_options().to_capabilities()
        else:
            if desired_capabilities is None:
                desired_capabilities = options.to_capabilities()
            else:
                desired_capabilities.update(options.to_capabilities())

        self.service = HiddenChromeService(
            executable_path,
            port=port,
            service_args=service_args,
            log_path=service_log_path)
        self.service.start()

        try:
            RemoteWebDriver.__init__(
                self,
                command_executor=remote_connection.ChromeRemoteConnection(
                    remote_server_addr=self.service.service_url,
                    keep_alive=keep_alive),
                desired_capabilities=desired_capabilities)
        except Exception:
            self.quit()
            raise
        self._is_remote = False

I removed some of the extra comments and doc string goo for brevity. You would then use this custom WebDriver the same way you'd use the official Chrome one in Selenium:

from selenium import webdriver
options = webdriver.ChromeOptions()
options.add_argument('headless')
headless_chrome = HiddenChromeWebDriver(chrome_options=options)

headless_chrome.get('http://www.example.com/')

headless_chrome.quit()

Finally, if creating a custom WebDriver is not for you and you don't mind a window flickering and disappearing then you can also use the win32gui library to hide the window after starting up:

# hide chromedriver console on Windows
def enumWindowFunc(hwnd, windowList):
    """ win32gui.EnumWindows() callback """
    text = win32gui.GetWindowText(hwnd)
    className = win32gui.GetClassName(hwnd)
    if 'chromedriver' in text.lower() or 'chromedriver' in className.lower():
        win32gui.ShowWindow(hwnd, False)
win32gui.EnumWindows(enumWindowFunc, [])
Stockist answered 18/10, 2018 at 21:46 Comment(2)
where i put this first code on the service.py i dont understand?Hofer
Create your own service.py wherever you want using the template I provided. Then import that Python file and use HiddenChromeWebDriver the same way you'd use the usual webdriverStockist
W
3

I found the solution to hide the console window when running Chromedriver:

I also got an error when importing CREATE_NO_WINDOW from win32process. To import it without error find the service.py file in Selenium files (like in Josh O'Brien's reply under this thread). Then instead of importing like this:

from win32process import CREATE_NO_WINDOW

you should instead import it from subprocess:

from subprocess import CREATE_NO_WINDOW

And then just add creationflags=CREATE_NO_WINDOW in the service.py file code part like this (also like in Josh O'Brien's reply):

            self.process = subprocess.Popen(cmd, env=self.env,
                                        close_fds=platform.system() != 'Windows',
                                        stdout=self.log_file,
                                        stderr=self.log_file,
                                        stdin=PIPE, creationflags=CREATE_NO_WINDOW)

And it works nicely for me, also when I used Pyinstaller to compile it to an EXE file.

Worms answered 2/4, 2021 at 22:2 Comment(0)
W
2

While launching chrome browser not seeing chromedriver console with the given sample code.

from selenium import webdriver
from selenium.webdriver.chrome.options import Options 
from time import sleep
options = webdriver.ChromeOptions()
prefs = {"download.default_directory":  r"C:\New_Download"}
options.add_experimental_option("prefs", prefs)
print(options.experimental_options)

chromeDriverPath = r'C:\drivers\chromedriver.exe'
driver = webdriver.Chrome(chromeDriverPath,chrome_options=options)
driver.get("http://google.com")
driver.set_window_position(0, 0)
driver.set_window_size(0, 0)
Workmanship answered 4/12, 2015 at 6:24 Comment(1)
The console window shows up when you use Selenium in a process without a console window. Running the Selenium code in a console window won't have any new pop-up console because there's already one it's attached to.Stockist
P
2

SELENIUM >4 Solution for Pyinstaller

Building from the answer by @Ali Sajjad

If you are using pyinstaller to bundle python code with GUI (like tkinter) and still want to hide the chromedriver console that pops out. Be sure to include the relevant path here...

    chrome_service = ChromeService('chromedriver')
    chrome_service.creationflags = CREATE_NO_WINDOW

The Service object from selenium take in the path of the chromedriver and thus should be replaced with the following..

    chrome_service = ChromeService(get_path('relative/path/to/chromedriver'))

Where get_path is a path connector that helps the scripts to find the files. Example of the resource_path function that works for me...

    def get_path(relative_path):
        """ Get the absolute path to the resource, works for dev and for PyInstaller """
        try:
           # PyInstaller creates a temp folder and stores path in _MEIPASS
           base_path = sys._MEIPASS
        except Exception:
           base_path = os.path.abspath(".")
        return os.path.join(base_path, relative_path)

Now, creating an instance would be:

            browser = webdriver.Chrome(service=chrome_service, options=options, executable_path=get_path('relative/path/to/chromedriver.exe'))

This should work with pyinstaller.

Purtenance answered 13/11, 2022 at 16:47 Comment(1)
Doesn't work for me. first: Cannot find reference '_MEIPASS' in 'sys.pyi' and not work. I post a new question here #74462347Triumphal
W
2

For me, the following solution did NOT work.

service = Service(EdgeChromiumDriverManager().install())
service.creationflags = CREATE_NO_WINDOW
driver = webdriver.Edge(options=self.options, service=service)

However, using selenium version 4.5.0 instead of 4.7.0 works like a charm.

Also see Unable to hide Chromedriver console with CREATE_NO_WINDOW

Whinstone answered 2/12, 2022 at 10:24 Comment(0)
V
0
    service = Service(ChromeDriverManager().install(), log_level='OFF')

    chrome_options = Options()
    chrome_options.add_argument("--headless")
    chrome_options.add_experimental_option("prefs", {"profile.managed_default_content_settings.images": 2})    
    chrome_options.add_argument("--disable-gpu")  # Desabilita o GPU

    browser = webdriver.Chrome(service=service, options=chrome_options)
Venturous answered 15/3 at 13:18 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.