rilascia Selenium chromedriver.exe dalla memoria


102

Ho impostato un codice Python per eseguire Selenium chromedriver.exe. Alla fine della corsa devo browser.close()chiudere l'istanza. ( browser = webdriver.Chrome()) Credo che dovrebbe essere rilasciato chromedriver.exedalla memoria (sono su Windows 7). Tuttavia, dopo ogni esecuzione, rimane chromedriver.exeun'istanza in memoria. Spero che ci sia un modo in cui posso scrivere qualcosa in Python per uccidere il chromedriver.exeprocesso. Ovviamente browser.close()non fa il lavoro. Grazie.


In conclusione ... devi interrompere il processo in qualche modo perché i progettisti non l'hanno integrato. Tutti gli altri modi potrebbero lasciare un processo in esecuzione e questo è sufficiente per giustificare l'uccisione.
Stephen G

Risposte:


73

per l'API Selenium, dovresti davvero chiamare browser.quit()poiché questo metodo chiuderà tutte le finestre e ucciderà il processo. Dovresti comunque usare browser.quit().

Tuttavia : sul mio posto di lavoro, abbiamo notato un enorme problema durante il tentativo di eseguire i test di chromedriver nella piattaforma Java, dove il chromedriver.exe esiste ancora anche dopo l'uso browser.quit(). Per contrastare questo, abbiamo creato un file batch simile a questo di seguito, che forza la chiusura dei processi.

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

Poiché chromedriver.exe non è un programma enorme e non consuma molta memoria, non dovresti eseguirlo ogni volta, ma solo quando presenta un problema. Ad esempio, quando si esegue Project-> Clean in Eclipse.


3
Non posso perdonare alcuna risposta che raccomandi l'uccisione dei processi senza menzionare anche il modo corretto per far terminare normalmente tali processi. Se utilizzi correttamente il quitmetodo, questo non dovrebbe essere un problema. L'uccisione forzata dei processi dovrebbe essere solo l'ultima risorsa e la tua risposta dovrebbe riflettere questo.
JimEvans

17
Vedi l'unico problema con questo, è che quando esegui il debug e interrompi l'esecuzione, il processo rimane ancora. Anche se fai clic su X, rimane ancora. questa è l' unica ragione per questo file batch. Ovviamente quitè la strada da percorrere, tuttavia nel mio esempio, se esegui il debug e interrompi l'esecuzione, non raggiunge mai il file quit.
ddavison

3
sto rispondendo a una delle domande: I hope there is a way I can write something to kill the chromedriver.exe process.. e sì, è carino! Java non lo fa
ddavison

3
A seconda del framework di test che usi, potresti anche ritrovarti con processi fantasma in giro se i test falliscono nella sua "configurazione". NUnit, ad esempio, non chiamerà il metodo TestFixtureTearDown se qualcosa nel metodo TestFixtureSetup fallisce -> crei il browser, fai alcune cose e quindi esegui il test. Se qualcosa va storto quando "fai delle cose", è tutto, il processo rimane lì.
Arran

1
Se utilizzi l'interfaccia DriverService, mantieni il servizio finché non hai finito con il driver e chiama anche DriverService.stop (). Per me, driver.quit () non era sufficiente perché stavo usando anche DriverService.
Kimball Robinson

38

browser.close() chiuderà solo la finestra di Chrome corrente.

browser.quit() dovrebbe chiudere tutte le finestre aperte, quindi uscire da webdriver.


9
Grazie Richard. browser.quit()ha chiuso tutte le finestre aperte. Ma chromedriver.exe non è stato chiuso. E c'era un messaggio di errore "InvalidURL: nonnumeric port:" port ".
KLI

5
OK. Ho provato browser = webdriver.Firefox(). Entrambi browser.close()e browser.quit()chiuderebbero tutte le finestre e rilascerebbero memoria. Tuttavia chromedriver non farebbe lo stesso.
KLI

Hey KLI. Qui dove lavoro, abbiamo notato che le stesse identiche cose accadono con chromedriver. Questo è il motivo per cui abbiamo un file batch che eseguiamo solo quando necessario. chromedriver.exe non è un processo di grandi dimensioni, ma presenta un problema quando proviamo ad eseguire Project-> Clean, ad esempio
ddavison

17

Teoricamente, chiamare browser.Quit chiuderà tutte le schede del browser e terminerà il processo.

Tuttavia, nel mio caso non ero in grado di farlo: poiché eseguivo più test in parallelo, non volevo eseguire un test per chiudere le finestre agli altri. Pertanto, quando i miei test finiscono di essere eseguiti, ci sono ancora molti processi "chromedriver.exe" rimasti in esecuzione.

Per ovviare a questo, ho scritto un semplice codice di pulizia (C #):

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

foreach(var chromeDriverProcess in chromeDriverProcesses)
{
     chromeDriverProcess.Kill();
}

Non ha aiutato. Il processo non viene
interrotto

@DenisKoreyba: non credo che il linguaggio di implementazione debba cambiare il comportamento. Su sistema operativo Windows, quando il processo non è tenuto da nessuno, puoi ucciderlo (anche se è tenuto, puoi forzarlo e ucciderlo). Stai cercando di interromperlo dopo la chiusura delle schede del browser?
Illidan

Sto usando C # per farlo, quello che ho detto a proposito di Java è che il processo di TeamCity viene eseguito sotto di esso. Rispondendo alla tua domanda: sì, prima invoco Dispose () e poi il tuo codice.
Denis Koreyba

Questo non funziona con il driver Chrome, almeno la versione 2.21. Il processo viene terminato ma la finestra della console viene ancora visualizzata, probabilmente perché alcuni processi figlio persistono. La risposta di aalhanane di seguito funziona.
Silent Sojourner

Ho inserito il codice di pulizia sopra menzionato nella sezione AssemblyCleanup di BaseDriverClass. Come posso verificare che il processo chromedriver.exe sia stato effettivamente ucciso?
monkrus

12

Ho avuto successo durante l'utilizzo driver.close()prima driver.quit(). In precedenza stavo solo usando driver.quit().


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


driver.close();

driver.quit();

Questo non ha funzionato per me. Chiamare driver.close (); chiuderà il browser e imposterà il driver su null. E poi non ha senso chiamare driver.quit (); poiché genererà un'eccezione nulla.
Priyanka,

l'implementazione ha alcuni cambiamenti nell'attuale selenio, potresti non aver bisogno di quit () se il processo viene ucciso. Assicurati che quando lo fai, il tuo task manager non dovrebbe avere il processo del browser ucciso.
Shantonu

7

È un po 'strano ma funziona per me. Ho avuto il problema simile, dopo alcuni scavi ho scoperto che c'era ancora un'azione dell'interfaccia utente in corso nel browser (caricamento dell'URL o giù di lì), quando ho premuto WebDriver.Quit().

La soluzione per me (anche se molto sgradevole) è stata quella di aggiungere Sleep()3 secondi prima di chiamare Quit ().


3
Grazie, in realtà ha funzionato anche per me. Stavo usando WebDriver.Quit()anche prima, ma a volte lasciava in vita un processo chrome.exe. Inoltre immagino che non stia accadendo su tutti i sistemi operativi.
Grengas

1
Questo ha funzionato anche per me! Potrebbe farti sentire un po 'sporco ma a volte a caso. I sonno sembrano essere ciò che il medico ha ordinato per i test dell'interfaccia utente.
Dan Csharpster

Lo stesso per me, chiudersi da solo o uscire da solo ha lasciato il processo del driver alle spalle. Facendo entrambe le cose ben pulite.
Mark Ball

Grande! Questo ha funzionato anche per me. Ho aggiunto Task.Delay (TimeSpan.FromSeconds (3)); prima di chiamare driver.Quit () e chiude tutti i file chromedriver.exe
Priyanka il

5

Questa risposta è come smaltire correttamente il driver in C #

Se vuoi usare un meccanismo "appropriato" da usare per "riordinare" dopo l'esecuzione ChromeDriver , dovresti usare IWebDriver.Dispose();

Esegue attività definite dall'applicazione associate alla liberazione, rilascio o ripristino di risorse non gestite. (Ereditato da IDisposable.)

Di solito implemento IDisposablesulla classe che si occupa diIWebDriver

public class WebDriverController : IDisposable
{
    public IWebDriver Driver;

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

e usalo come:

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

Spero che questo ti faccia risparmiare tempo


6
Posso confermare che ci sono ancora problemi con questa strategia! Sto usando Selenium WebDriver API .NET v3.13.1.0, la mia istanza di Chrome è aggiornata, così come il mio Windows 10 ... Sto usando ChromeDriver (che implementa IDisposable per ereditarietà) in questo modo: using (var driver = new ChromeDriver()) { //my code here } A volte, non sempre, "qualcosa" (non so cosa ??) accade ed chromedriver.exeè ancora inedito secondo il mio taskmanager.
Hauns TM

Sì, anche questo non risolve il bug per me.
Pxtl

4

Elimina più processi dalla riga di comando La prima cosa che devi fare è aprire un prompt dei comandi, quindi utilizzare il comando taskkill con la seguente sintassi:

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

Questi parametri uccideranno forzatamente qualsiasi processo che corrisponda al nome dell'eseguibile specificato. Ad esempio, per uccidere tutti i processi iexplore.exe, useremmo:

taskkill /F /IM iexplore.exe

inserisci qui la descrizione dell'immagine


3

Codice c #

using System.Diagnostics;

using 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;
            }
        }

    }

e questa funzione

        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.
        }
    }

Chiamando

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

            }

Ho applicato il tuo codice come pulizia finale. Finora sembra funzionare. Buon lavoro!
Exzile

2

Ho avuto lo stesso problema durante l'esecuzione in Python e ho dovuto eseguire manualmente il comando "killall" per terminare tutti i processi. Tuttavia, quando ho implementato il driver utilizzando il protocollo di gestione del contesto Python , tutti i processi erano spariti. Sembra che l'interprete Python faccia un ottimo lavoro nel ripulire le cose.

Ecco l'implementazione:

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()

E l'utilizzo:

with Browser() as browser:
    browser.navigate_to_page()

2

Quindi, puoi usare quanto segue:

driver.close()

Chiudi il browser (emula la pressione del pulsante di chiusura)

driver.quit()

Esci dal browser (emula selezionando l'opzione esci)

driver.dispose()

Esci dal browser (prova a chiudere ogni scheda, quindi esci)

Tuttavia, se stai ANCORA riscontrando problemi con istanze sospese (come lo ero io), potresti voler uccidere anche l'istanza. Per fare ciò, è necessario il PID dell'istanza di 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)

Se è rimasta un'istanza di Chrome dopo, mi mangio il cappello. :(


2

Codice Python:

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

1

So che questa è una vecchia domanda, ma ho pensato di condividere ciò che ha funzionato per me. Avevo problemi con Eclipse: non avrebbe ucciso i processi, quindi ho avuto un sacco di processi fantasma in giro dopo aver testato il codice usando il runner Eclipse.

La mia soluzione era eseguire Eclipse come amministratore. Questo ha risolto il problema per me. Sembra che Windows non consentisse a Eclipse di chiudere il processo generato.


Questo ha molto senso, ma nel mio caso non ha funzionato, chromedriver.exerimane visibile tra i processi del Task Manager indipendentemente dal fatto che avvii Eclipse come amministratore o utente normale. È possibile che nel mio caso questo sia il problema, perché chromedriver.exeè a 32 bit e il mio JRE è a 64 bit. Eclipse Neon.1a (4.6.1), Windows 8.1 Pro 64 bit, Java 1.8.0_92-b14.
SantiBailors

1

Ho usato il seguente in nightwatch.js in afterEach hooks.

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

.closeWindow () chiude semplicemente la finestra. (Ma non funzionerà per più finestre aperte). Mentre .end () termina tutti i rimanenti processi chrome.


0

Ho questo problema. Sospetto che sia dovuto alla versione di Serenity BDD e Selenium. Il processo chromedriver non viene rilasciato fino al termine dell'intera suite di test. Ci sono solo 97 test, ma avere 97 processi che consumano la memoria di un server che non ha molte risorse potrebbe avere un effetto sulle prestazioni.

Per affrontare ho fatto 2 cose (questo è specifico per Windows).

  1. prima di ogni test (annotato con @Before) ottieni l'id del processo (PID) del processo chromedriver 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. dopo ogni test (annotato con @After) uccidi il PID con:

    Runtime.getRuntime().exec("taskkill /F /PID " + pid);
    

0

Sono venuto qui inizialmente pensando che sicuramente questo sarebbe stato risolto / risolto ma dopo aver letto tutte le risposte sono rimasto un po 'sorpreso che nessuno abbia provato a chiamare tutti e tre i metodi insieme:

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
}

Ero qui solo per cercare risposte e non intendevo fornirne una. Quindi la soluzione di cui sopra si basa solo sulla mia esperienza. Stavo usando il driver chrome in un'app console C # e sono stato in grado di ripulire i processi in sospeso solo dopo aver chiamato tutti e tre i metodi insieme.


0

Per gli utenti Ubuntu / Linux: - il comando è o pkillo killall. pkillè generalmente raccomandato, poiché su alcuni sistemi, killallin realtà ucciderà tutti i processi.


0

Sto usando Goniometro con directConnect. La disabilitazione dell'opzione "--no-sandbox" ha risolto il problema per me.

// 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"]
  }
},

0
  • Assicurati di ottenere l'istanza del driver come Singleton
  • quindi applicare alla fine
  • driver.close ()
  • driver.quit ()

Nota: ora se vediamo il task manager non troverai alcun driver o processo di Chrome ancora sospeso


0

Ho esaminato tutte le risposte e le ho testate tutte. Li ho praticamente raccolti tutti in uno come una "chiusura di sicurezza". Questo in c #

NOTA è possibile modificare il parametro dall'app IModule a quello del driver effettivo.

 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.
        }
    }

}

0

Osservato nella versione 3.141.0:

Se inizializzi il tuo ChromeDriver solo con ChromeOptions, quit () non chiuderà chromedriver.exe.

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

Se crei e passi un ChromeDriverService, quit () chiuderà chromedriver.exe correttamente.

    ChromeDriverService driverService = ChromeDriverService.CreateDefaultService();
    ChromeOptions chromeOptions = new ChromeOptions();
    ChromeDriver driver = new ChromeDriver(driverService, chromeOptions);
    // .. do stuff ..
    driver.quit()

Questa è la soluzione in Java credo. Almeno, ha funzionato per me
Isabelle T.

0

Uso semplicemente in ogni test un metodo tearDown () come segue e non ho alcun problema.

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

Dopo essere usciti dall'istanza del driver, cancellala dalla cache con driver = null

Spero che la risposta alla domanda


0

C'è un altro modo che funziona solo per Windows, ma ora è deprecato. funziona per le versioni precedenti di selenio (funziona sulla versione 3.11.0).

import org.openqa.selenium.os.WindowsUtils;

 WindowsUtils.killByName("chromedriver.exe") // any process name you want

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.