liberar Selenium chromedriver.exe de la memoria

102

Configuré un código de Python para ejecutar Selenium chromedriver.exe. Al final de la ejecución, tengo browser.close()que cerrar la instancia. ( browser = webdriver.Chrome()) Creo que debería liberarse chromedriver.exede la memoria (estoy en Windows 7). Sin embargo, después de cada ejecución, queda una chromedriver.exeinstancia en la memoria. Espero que haya una forma de escribir algo en Python para matar el chromedriver.exeproceso. Obviamente browser.close()no hace el trabajo. Gracias.

KLI
fuente
En pocas palabras ... tienes que matar el proceso de alguna manera porque los diseñadores no lo incorporaron. Todas las demás formas pueden dejar un proceso en ejecución y eso es suficiente para justificar la eliminación.
Stephen G

Respuestas:

73

según la API de Selenium, debería llamar, browser.quit()ya que este método cerrará todas las ventanas y matará el proceso. Aún debe usar browser.quit().

Sin embargo : en mi lugar de trabajo, hemos notado un gran problema al intentar ejecutar pruebas de chromedriver en la plataforma Java, donde el chromedriver.exe todavía existe incluso después de usarlo browser.quit(). Para contrarrestar esto, creamos un archivo por lotes similar al siguiente, que solo fuerza el cierre de los procesos.

kill_chromedriver.bat

@echo off
rem   just kills stray local chromedriver.exe instances.
rem   useful if you are trying to clean your project, and your ide is complaining.

taskkill /im chromedriver.exe /f

Dado que chromedriver.exe no es un programa enorme y no consume mucha memoria, no debería tener que ejecutar esto cada vez, sino solo cuando presenta un problema. Por ejemplo, al ejecutar Proyecto-> Limpiar en Eclipse.

ddavison
fuente
3
No puedo condonar ninguna respuesta que recomiende matar procesos sin mencionar también la forma correcta de que esos procesos terminen normalmente. Si usa correctamente el quitmétodo, esto no debería ser un problema. La eliminación forzada de los procesos solo debería ser un último recurso, y su respuesta debería reflejar eso.
JimEvans
17
Vea que el único problema con esto es que cuando depura y mata la ejecución, el proceso aún permanece. Incluso si hace clic Xen, todavía permanece. esa es la ÚNICA razón para este archivo por lotes. Obviamente quites el camino a seguir, sin embargo, en mi ejemplo, si depura y detiene la ejecución, nunca llega al quit.
ddavison
3
Estoy respondiendo una de las preguntas: I hope there is a way I can write something to kill the chromedriver.exe process.. y sí, ¡eso es lindo! Java no hace eso
ddavison
3
Dependiendo del marco de prueba que use, también puede terminar con procesos fantasmas si las pruebas fallan en su "configuración". NUnit, por ejemplo, no llamará al método TestFixtureTearDown si algo en el método TestFixtureSetup falla -> usted crea el navegador, hace algunas cosas y luego ejecuta la prueba. Si algo sale mal cuando "haces algunas cosas", eso es todo, el proceso se queda ahí.
Arran
1
Si usa la interfaz DriverService, mantenga el servicio hasta que haya terminado con el controlador y llame también a DriverService.stop (). Para mí, el driver.quit () no fue suficiente porque también estaba usando DriverService.
Kimball Robinson
38

browser.close() cerrará solo la ventana de Chrome actual.

browser.quit() debe cerrar todas las ventanas abiertas, luego salir de webdriver.

Ricardo
fuente
9
Gracias Richard. browser.quit()cerró todas las ventanas abiertas. Pero no se salió de chromedriver.exe. Y había un mensaje de error 'InvalidURL: nonnumeric port:' port ''.
KLI
5
OKAY. Lo intenté browser = webdriver.Firefox(). Ambos browser.close()y browser.quit()cerrarían todas las ventanas y liberarían memoria. Sin embargo, chromedriver no haría lo mismo.
KLI
Hola KLI. Aquí, donde trabajo, hemos notado exactamente las mismas cosas que suceden con chromedriver. Es por eso que tenemos un archivo por lotes que solo ejecutamos cuando lo necesitamos. chromedriver.exe no es un gran proceso, pero presenta un problema cuando intentamos ejecutar Proyecto-> Limpiar, por ejemplo
ddavison
17

En teoría, llamar a browser.Quit cerrará todas las pestañas del navegador y terminará el proceso.

Sin embargo, en mi caso no pude hacer eso, ya que ejecuté varias pruebas en paralelo, no quería hacer una prueba para cerrar ventanas a otras. Por lo tanto, cuando mis pruebas terminan de ejecutarse, todavía quedan muchos procesos "chromedriver.exe" en ejecución.

Para superar eso, escribí un código de limpieza simple (C #):

Process[] chromeDriverProcesses =  Process.GetProcessesByName("chromedriver");

foreach(var chromeDriverProcess in chromeDriverProcesses)
{
     chromeDriverProcess.Kill();
}
Illidan
fuente
No ayudó. El proceso no se mata cuando se ejecuta en Java
Denis Koreyba
@DenisKoreyba: No creo que el lenguaje de implementación deba cambiar el comportamiento. En el sistema operativo Windows, cuando el proceso no está en manos de nadie, puede eliminarlo (incluso si se mantuvo, puede forzarlo y eliminarlo). ¿Está intentando eliminarlo después de que se hayan cerrado las pestañas del navegador?
Illidan
Estoy usando C # para hacer esto, lo que dije sobre Java es que el proceso de TeamCity se ejecuta bajo él. Respondiendo a su pregunta: sí, primero invoco Dispose () y luego su código.
Denis Koreyba
Esto no funciona en el controlador de Chrome, al menos la versión 2.21. El proceso se mata pero la ventana de la consola aún se muestra, probablemente porque algún proceso hijo aún persiste. La respuesta de aalhanane a continuación funciona.
Silent Sojourner
Inserté el código de limpieza mencionado anteriormente en la sección AssemblyCleanup de BaseDriverClass. ¿Cómo puedo verificar que el proceso chromedriver.exe se haya eliminado realmente?
monkrus
12

Tuve éxito al usar driver.close()antes driver.quit(). Anteriormente solo usaba driver.quit().

kinghat
fuente
12
//Calling close and then quit will kill the driver running process.


driver.close();

driver.quit();
Shantonu
fuente
Esto no funcionó para mí. Llamando driver.close (); cerrará el navegador y establecerá el controlador en nulo. Y luego no tiene sentido llamar a driver.quit (); ya que arrojará una excepción nula.
Priyanka
la implementación tiene algunos cambios en el selenio actual, es posible que no necesite salir () si se mata el proceso. Asegúrese de que cuando haga eso, su administrador de tareas no debería tener el proceso del navegador interrumpido.
Shantonu
7

Es un poco extraño pero me funciona. Tuve un problema similar, después de investigar un poco, descubrí que todavía había una acción de interfaz de usuario en el navegador (carga de URL más o menos), cuando presioné WebDriver.Quit().

La solución para mí (aunque muy desagradable) fue agregar una Sleep()de 3 segundos antes de llamar a Quit ().

Alpana Chauhan
fuente
3
Gracias, esto también funcionó para mí. También estaba usando WebDriver.Quit()antes, pero a veces dejaba vivo un proceso chrome.exe. Además, supongo que no está sucediendo en todos los sistemas operativos.
Grengas
1
¡Esto funcionó para mí también! Puede hacer que se sienta un poco sucio, pero a veces es aleatorio. Los sueños parecen ser lo que el médico ordenó para las pruebas de IU.
Dan Csharpster
Lo mismo para mí, cerrar solo o salir solo dejó el proceso del controlador atrás. Haciendo ambos limpios muy bien.
Mark Ball
¡Excelente! Esto funcionó para mí también. Agregué Task.Delay (TimeSpan.FromSeconds (3)); antes de llamar a driver.Quit () y está cerrando todos los archivos chromedriver.exe
Priyanka
5

Esta respuesta es cómo deshacerse correctamente del controlador en C #

Si desea utilizar un mecanismo 'adecuado' que debería utilizarse para 'ordenar' después de ejecutar ChromeDriver , debería utilizar IWebDriver.Dispose();

Realiza tareas definidas por la aplicación asociadas con la liberación, liberación o restablecimiento de recursos no administrados. (Heredado de IDisposable).

Normalmente lo implemento IDisposableen la clase que se ocupa deIWebDriver

public class WebDriverController : IDisposable
{
    public IWebDriver Driver;

    public void Dispose()
    {
        this.Driver.Dispose();
    }
}

y utilícelo como:

using (var controller = new WebDriverController())
{
  //code goes here
}

Espero que esto te ahorre algo de tiempo

Matas Vaitkevicius
fuente
6
¡Puedo confirmar que todavía hay problemas con esta estrategia! Estoy usando Selenium WebDriver API .NET v3.13.1.0, mi instancia de Chrome está actualizada, al igual que mi Windows 10 ... Estoy usando ChromeDriver (que implementa IDisposable por herencia) así: using (var driver = new ChromeDriver()) { //my code here } A veces, no siempre, "algo" (¿no sé qué?) sucede y chromedriver.exeaún no se ha publicado según mi administrador de tareas.
Hauns TM
Sí, esto tampoco me soluciona el error.
Pxtl
4

Elimine varios procesos desde la línea de comandos Lo primero que debe hacer es abrir un símbolo del sistema y luego usar el comando taskkill con la siguiente sintaxis:

taskkill /F /IM <processname.exe> /T

Estos parámetros eliminarán por la fuerza cualquier proceso que coincida con el nombre del ejecutable que especifique. Por ejemplo, para eliminar todos los procesos iexplore.exe, usaríamos:

taskkill /F /IM iexplore.exe

ingrese la descripción de la imagen aquí

sumit kumar pradhan
fuente
3

Código c #

utilizando System.Diagnostics;

utilizando System.Management;

        public void KillProcessAndChildren(string p_name)
    {
        ManagementObjectSearcher searcher = new ManagementObjectSearcher
          ("Select * From Win32_Process Where Name = '"+ p_name +"'");

        ManagementObjectCollection moc = searcher.Get();
        foreach (ManagementObject mo in moc)
        {

            try
            {
                KillProcessAndChildren(Convert.ToInt32(mo["ProcessID"]));
            }
            catch (ArgumentException)
            {
                break;
            }
        }

    }

y esta función

        public void KillProcessAndChildren(int pid)
    {
        ManagementObjectSearcher searcher = new ManagementObjectSearcher
         ("Select * From Win32_Process Where ParentProcessID=" + pid);
        ManagementObjectCollection moc = searcher.Get();
        foreach (ManagementObject mo in moc)
        {

            try
            {
                KillProcessAndChildren(Convert.ToInt32(mo["ProcessID"]));
            }
            catch
            {
                break;
            }
        }

        try
        {
            Process proc = Process.GetProcessById(pid);

            proc.Kill();
        }
        catch (ArgumentException)
        {
            // Process already exited.
        }
    }

Vocación

                try
            {
                 KillProcessAndChildren("chromedriver.exe");
            }
            catch
            {

            }
aalhanane
fuente
He aplicado su código como limpieza final. Hasta ahora parece funcionar. ¡Buen trabajo!
Exzile
2

Tuve el mismo problema al ejecutarlo en Python y tuve que ejecutar manualmente el comando 'killall' para matar todos los procesos. Sin embargo, cuando implementé el controlador usando el protocolo de administración de contexto de Python , todos los procesos desaparecieron. Parece que el intérprete de Python hace un buen trabajo limpiando las cosas.

Aquí está la implementación:

class Browser:
    def __enter__(self):
        self.options = webdriver.ChromeOptions()
        self.options.add_argument('headless')
        self.driver = webdriver.Chrome(chrome_options=self.options)
        return self

    def __exit__(self, exc_type, exc_val, exc_tb):
        self.driver.close()
        self.driver.quit()

Y el uso:

with Browser() as browser:
    browser.navigate_to_page()
Mago
fuente
2

Entonces, puedes usar lo siguiente:

driver.close()

Cerrar el navegador (emula presionar el botón de cierre)

driver.quit()

Salir del navegador (emula la selección de la opción de salir)

driver.dispose()

Salir del navegador (intenta cerrar todas las pestañas y luego salir)

Sin embargo, si TODAVÍA tiene problemas con las instancias colgadas (como yo), es posible que también desee eliminar la instancia. Para hacer eso, necesita el PID de la instancia de Chrome.

import os
import signal 
driver = webdriver.Chrome()
driver.get(('http://stackoverflow.com'))

def get_pid(passdriver):
    chromepid = int(driver.service.process.pid)
    return (chromepid)

def kill_chrome(thepid)
    try:
        os.kill(pid, signal.SIGTERM)
        return 1
    except:
        return 0

print ("Loaded thing, now I'mah kill it!")
try:
    driver.close()
    driver.quit()
    driver.dispose()
except:
    pass

kill_chrome(chromepid)

Si queda una instancia de Chrome después de eso, me comeré mi sombrero. :(

Rue Lazzaro
fuente
2

Código Python:

try:
    # do my automated tasks
except:
    pass
finally:
    driver.close()
    driver.quit()
Moshe Slavin
fuente
1

Sé que esta es una pregunta algo antigua, pero pensé en compartir lo que funcionó para mí. Estaba teniendo problemas con Eclipse, no mataría los procesos, por lo que tenía un montón de procesos fantasmas dando vueltas después de probar el código usando el corredor de Eclipse.

Mi solución fue ejecutar Eclipse como administrador. Eso me lo arregló. Parece que Windows no permitía que Eclipse cerrara el proceso que generó.

forresthopkinsa
fuente
Esto tiene mucho sentido, pero en mi caso no funcionó, chromedriver.exepermanece visible entre los procesos del Administrador de tareas sin importar que inicie Eclipse como administrador o usuario normal. Es posible que en mi caso este sea ​​el problema, porque chromedriver.exees de 32 bits y mi JRE es de 64 bits. Eclipse Neon.1a (4.6.1), Windows 8.1 Pro de 64 bits, Java 1.8.0_92-b14.
SantiBailors
1

He usado lo siguiente en nightwatch.js en afterEach hooks.

afterEach: function(browser, done) {
    // performing an async operation
    setTimeout(function() {
        // finished async duties
        done();
        browser.closeWindow();
        browser.end();
    }, 200);
}

.closeWindow () simplemente cierra la ventana. (Pero no funcionará para varias ventanas abiertas). Mientras que .end () finaliza todos los procesos restantes de Chrome.

Simón Correia
fuente
0

Tengo este problema. Sospecho que se debe a la versión de Serenity BDD y Selenium. El proceso de cromedriver nunca se libera hasta que finaliza todo el conjunto de pruebas. Solo hay 97 pruebas, pero el hecho de que 97 procesos consuman la memoria de un servidor que no tiene muchos recursos puede afectar el rendimiento.

Para abordar hice 2 cosas (esto es específico de Windows).

  1. antes de cada prueba (anotado con @Before) obtenga el ID de proceso (PID) del proceso del controlador cromado con:

    List<Integer> pids = new ArrayList<Integer>();
    String out;
    Process p = Runtime.getRuntime().exec("tasklist /FI \"IMAGENAME eq chromedriver.exe*\"");
    BufferedReader input = new BufferedReader(new InputStreamReader(p.getInputStream()));
    while ((out = input.readLine()) != null) {
        String[] items = StringUtils.split(out, " ");
        if (items.length > 1 && StringUtils.isNumeric(items[1])) {
            pids.add(NumberUtils.toInt(items[1]));
        }
    }
    
  2. después de cada prueba (anotado con @After) elimine el PID con:

    Runtime.getRuntime().exec("taskkill /F /PID " + pid);
    
Dean McNabb
fuente
0

Vine aquí inicialmente pensando que seguramente esto se habría respondido / resuelto, pero después de leer todas las respuestas, me sorprendió un poco que nadie intentara reunir los tres métodos:

try
{
    blah
}
catch
{
    blah
}
finally
{
    driver.Close(); // Close the chrome window
    driver.Quit(); // Close the console app that was used to kick off the chrome window
    driver.Dispose(); // Close the chromedriver.exe
}

Solo estaba aquí para buscar respuestas y no tenía la intención de proporcionar una. Entonces, la solución anterior se basa solo en mi experiencia. Estaba usando el controlador de Chrome en una aplicación de consola C # y pude limpiar los procesos persistentes solo después de llamar a los tres métodos juntos.

Louie Bao
fuente
0

Para usuarios de Ubuntu / Linux: - el comando es pkillo killall. pkillgeneralmente se recomienda, ya que en algunos sistemas, killallrealmente matará todos los procesos.

Manmohan Singh
fuente
0

Estoy usando Protractor con directConnect. La desactivación de la opción "--no-sandbox" solucionó el problema.

// Capabilities to be passed to the webdriver instance.
capabilities: {
  'directConnect': true,
  'browserName': 'chrome',
  chromeOptions: {
      args: [
        //"--headless",
        //"--hide-scrollbars",
        "--disable-software-rasterizer",
        '--disable-dev-shm-usage',
        //"--no-sandbox",
        "incognito",
        "--disable-gpu",
        "--window-size=1920x1080"]
  }
},
Georgi Ekimov
fuente
0
  • Asegúrese de obtener la instancia del controlador como Singleton
  • luego Aplicar al final
  • driver.close ()
  • driver.quit ()

Nota: Ahora, si vemos el administrador de tareas, no encontrará ningún controlador o proceso de Chrome aún colgando.

Sarath
fuente
0

He mirado todas las respuestas y las he probado todas. Prácticamente los recopilé todos en uno como un 'Cierre de seguridad'. Esto en c #

NOTA: puede cambiar el parámetro de la aplicación IModule al del controlador real.

 public class WebDriverCleaner
{

    public static void CloseWebDriver(IModule app)
    {
        try
        {
            if (app?.GetDriver() != null)
            {
                app.GetDriver().Close();
                Thread.Sleep(3000); // Gives time for everything to close before quiting
                app.GetDriver().Quit();
                app.GetDriver().Dispose();
                KillProcessAndChildren("chromedriver.exe"); // One more to make sure we get rid of them chromedrivers.
            }
        }
        catch (Exception e)
        {
            Console.WriteLine(e);
            throw;
        }
    }

    public static void KillProcessAndChildren(string p_name)
    {
        ManagementObjectSearcher searcher = new ManagementObjectSearcher
            ("Select * From Win32_Process Where Name = '" + p_name + "'");

        ManagementObjectCollection moc = searcher.Get();
        foreach (ManagementObject mo in moc)
        {
            try
            {
                KillProcessAndChildren(Convert.ToInt32(mo["ProcessID"]));
            }
            catch (ArgumentException)
            {
                break;
            }
        }

    }


    public static void KillProcessAndChildren(int pid)
    {
        ManagementObjectSearcher searcher = new ManagementObjectSearcher("Select * From Win32_Process Where ParentProcessID=" + pid);
        ManagementObjectCollection moc = searcher.Get();

        foreach (ManagementObject mo in moc)
        {
            try
            {
                KillProcessAndChildren(Convert.ToInt32(mo["ProcessID"]));
            }
            catch
            {
                break;
            }
        }

        try
        {
            Process proc = Process.GetProcessById(pid);
            proc.Kill();
        }
        catch (ArgumentException)
        {
            // Process already exited.
        }
    }

}
Exzile
fuente
0

Observado en la versión 3.141.0:

Si inicializa su ChromeDriver solo con ChromeOptions, quit () no cerrará chromedriver.exe.

    ChromeOptions chromeOptions = new ChromeOptions();
    ChromeDriver driver = new ChromeDriver(chromeOptions);
    // .. do stuff ..
    driver.quit()

Si crea y pasa un ChromeDriverService, quit () cerrará chromedriver.exe correctamente.

    ChromeDriverService driverService = ChromeDriverService.CreateDefaultService();
    ChromeOptions chromeOptions = new ChromeOptions();
    ChromeDriver driver = new ChromeDriver(driverService, chromeOptions);
    // .. do stuff ..
    driver.quit()
vhoang
fuente
Esta es la solución en Java, creo. Al menos, funcionó para mí
Isabelle T.
0

Simplemente uso en cada prueba un método tearDown () como sigue y no tengo ningún problema.

@AfterTest
public void tearDown() {
    driver.quit();
    driver = null;
}

Después de salir de la instancia del controlador, límpiela de la caché con driver = null

Espero la respuesta a la pregunta

Jamil
fuente
0

Hay otra forma que funciona solo para Windows, pero ahora está en desuso. funciona para versiones anteriores de selenio (funciona en la versión 3.11.0).

import org.openqa.selenium.os.WindowsUtils;

 WindowsUtils.killByName("chromedriver.exe") // any process name you want
Norayr Sargsyan
fuente
0

Debe aplicar cerca antes de dejar de fumar

driver.close()
driver.quit()
Sara Bouraya
fuente
No funciona, chromedriver.exe sigue abierto
Pedro Joaquín
1
--Editar -> Se eliminó "driver.close ()" y funcionó
Pedro Joaquín