Geben Sie Selenium chromedriver.exe aus dem Speicher frei


102

Ich habe einen Python-Code eingerichtet, um Selenium auszuführen chromedriver.exe. Am Ende des Laufs muss ich browser.close()die Instanz schließen. ( browser = webdriver.Chrome()) Ich glaube, es sollte chromedriver.exeaus dem Speicher freigegeben werden (ich bin unter Windows 7). Nach jedem Lauf chromedriver.exeverbleibt jedoch eine Instanz im Speicher. Ich hoffe, es gibt eine Möglichkeit, etwas in Python zu schreiben, um den chromedriver.exeProzess zu beenden . Offensichtlich browser.close()macht die Arbeit nicht. Vielen Dank.


Fazit ... Sie müssen den Prozess irgendwie beenden, weil die Designer ihn nicht eingebaut haben. Alle anderen Möglichkeiten können dazu führen, dass ein Prozess ausgeführt wird, und das reicht aus, um den Vorgang zu rechtfertigen.
Stephen G

Antworten:


73

Gemäß der Selenium-API sollten Sie wirklich aufrufen, browser.quit()da diese Methode alle Fenster schließt und den Prozess abbricht. Sie sollten immer noch verwendenbrowser.quit() .

Allerdings : An meinem Arbeitsplatz haben wir ein großes Problem festgestellt, als wir versucht haben, Chromedriver-Tests auf der Java-Plattform auszuführen, auf der die chromedriver.exe auch nach der Verwendung noch vorhanden istbrowser.quit() . Um dem entgegenzuwirken, haben wir eine Batch-Datei ähnlich der folgenden erstellt, die nur das Schließen der Prozesse erzwingt.

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

Da chromedriver.exe kein großes Programm ist und nicht viel Speicher verbraucht, sollten Sie dies nicht jedes Mal ausführen müssen, sondern nur, wenn es ein Problem darstellt. Zum Beispiel, wenn Sie Project-> Clean in Eclipse ausführen.


3
Ich kann keine Antwort dulden, die das Beenden von Prozessen empfiehlt, ohne auch die richtige Art und Weise zu erwähnen, wie diese Prozesse normal enden. Wenn Sie die quitMethode ordnungsgemäß verwenden , sollte dies kein Problem sein. Das gewaltsame Abschalten der Prozesse sollte nur ein letzter Ausweg sein, und Ihre Antwort sollte dies widerspiegeln.
JimEvans

17
Das einzige Problem dabei ist, dass beim Debuggen und Beenden der Ausführung der Prozess weiterhin besteht. Auch wenn Sie auf das klicken X, bleibt es bestehen. Das ist der EINZIGE Grund für diese Batch-Datei. Offensichtlich quitist der richtige Weg, aber in meinem Beispiel, wenn Sie debuggen und die Ausführung stoppen - es erreicht nie die quit.
Ddavison

3
Ich beantworte eine der Fragen : I hope there is a way I can write something to kill the chromedriver.exe process.. und ja das ist schön Java macht das nicht
ddavison

3
Abhängig von dem von Ihnen verwendeten Testframework kann es auch zu Phantomprozessen kommen, wenn die Tests im "Setup" fehlschlagen. NUnit ruft beispielsweise die TestFixtureTearDown-Methode nicht auf, wenn etwas in der TestFixtureSetup-Methode fehlschlägt -> Sie erstellen den Browser, führen einige Schritte aus und führen dann den Test aus. Wenn etwas schief geht, wenn "Sie ein paar Sachen machen", dann ist der Prozess dort.
Arran

1
Wenn Sie die DriverService-Schnittstelle verwenden, halten Sie den Dienst fest, bis Sie mit dem Treiber fertig sind, und rufen Sie auch DriverService.stop () auf. Für mich war die Datei driver.quit () nicht genug, da ich auch DriverService verwendet habe.
Kimball Robinson

38

browser.close() schließt nur das aktuelle Chromfenster.

browser.quit() sollte alle geöffneten Fenster schließen und dann den Webdriver beenden.


9
Danke Richard. browser.quit()habe alle geöffneten Fenster geschlossen. Aber chromedriver.exe wurde nicht beendet. Und es gab eine Fehlermeldung 'InvalidURL: nicht numerischer Port:' Port ''.
KLI

5
OK. Ich habe es versucht browser = webdriver.Firefox(). Beides browser.close()und browser.quit()würde alle Fenster schließen und Speicher freigeben. Chromedriver würde jedoch nicht dasselbe tun.
KLI

Hey KLI. Hier, wo ich arbeite, haben wir genau die gleichen Dinge bemerkt, die mit dem Chromedriver passieren. Aus diesem Grund haben wir eine Batch-Datei, die wir nur bei Bedarf ausführen. chromedriver.exe ist kein großer Prozess, aber es stellt ein Problem dar, wenn wir versuchen, Project-> Clean zum Beispiel
auszuführen

17

Theoretisch werden durch das Aufrufen von browser.Quit alle Browser-Registerkarten geschlossen und der Vorgang abgebrochen.

In meinem Fall war ich jedoch nicht dazu in der Lage - da ich mehrere Tests gleichzeitig ausführte, wollte ich nicht einen Test durchführen, um Fenster für andere zu schließen. Wenn meine Tests beendet sind, werden daher noch viele "chromedriver.exe" -Prozesse ausgeführt.

Um dies zu überwinden, habe ich einen einfachen Bereinigungscode (C #) geschrieben:

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

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

Es hat nicht geholfen. Der Prozess wird nicht beendet, wenn er unter Java ausgeführt wird
Denis Koreyba

@DenisKoreyba: Ich denke nicht, dass die Sprache der Implementierung das Verhalten ändern sollte. Wenn unter Windows ein Prozess von niemandem gehalten wird, können Sie ihn beenden (selbst wenn er gehalten wird, können Sie ihn erzwingen und beenden). Versuchen Sie, es zu beenden, nachdem die Browser-Registerkarten geschlossen wurden?
Illidan

Ich benutze C #, um dies zu tun. Was ich über Java gesagt habe, ist, dass der Prozess von TeamCity darunter ausgeführt wird. Beantwortung Ihrer Frage: Ja, zuerst rufe ich Dispose () und dann Ihren Code auf.
Denis Koreyba

Dies funktioniert nicht mit dem Chrome-Treiber, zumindest Version 2.21. Der Prozess wird abgebrochen, aber das Konsolenfenster wird weiterhin angezeigt, wahrscheinlich weil ein untergeordneter Prozess weiterhin besteht. Die Antwort von Aalhanane unten funktioniert.
Silent Sojourner

Ich habe den oben genannten Bereinigungscode in den AssemblyCleanup-Abschnitt der BaseDriverClass eingefügt. Wie kann ich überprüfen, ob der Prozess chromedriver.exe tatsächlich beendet wurde?
monkrus

12

Ich hatte Erfolg bei der Verwendung driver.close()vor driver.quit(). Ich habe vorher nur benutzt driver.quit().


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


driver.close();

driver.quit();

Das hat bei mir nicht funktioniert. Aufruf von driver.close (); schließt den Browser und setzt den Treiber auf null. Und dann macht es keinen Sinn, driver.quit () aufzurufen. da es null Ausnahme auslösen wird.
Priyanka

Die Implementierung hat einige Änderungen im aktuellen Selen. Möglicherweise müssen Sie nicht beenden (), wenn der Prozess abgebrochen wird. Stellen Sie dabei sicher, dass der Browserprozess in Ihrem Task-Manager nicht abgebrochen wird.
Shantonu

7

Es ist irgendwie seltsam, aber es funktioniert bei mir. Ich hatte das ähnliche Problem, nach einigem Graben stellte ich fest, dass im Browser noch eine UI-Aktion ausgeführt wurde (URL-Laden oder so), als ich drückteWebDriver.Quit() .

Die Lösung für mich (obwohl sehr böse) war, Sleep()3 Sekunden vor dem Aufruf von Quit () hinzuzufügen .


3
Danke, das hat auch bei mir funktioniert. Ich habe es WebDriver.Quit()auch schon früher verwendet, aber manchmal hat es einen chrome.exe-Prozess am Leben gelassen. Ich denke auch, dass es nicht auf allen Betriebssystemen passiert.
Grengas

1
Das hat auch bei mir funktioniert! Es kann dazu führen, dass Sie sich ein bisschen schmutzig fühlen, aber manchmal zufällig Thread.Sleeps scheinen das zu sein, was der Arzt für UI-Tests bestellt hat.
Dan Csharpster

Das Gleiche gilt für mich, wenn Sie alleine schließen oder alleine beenden, bleibt der Treiberprozess zurück. Beides gut aufgeräumt.
Mark Ball

Toll! Das hat auch bei mir funktioniert. Ich habe Task.Delay (TimeSpan.FromSeconds (3)) hinzugefügt. bevor Sie driver.Quit () aufrufen und alle chromedriver.exe-Dateien schließen
Priyanka

5

Mit dieser Antwort können Sie den Treiber in C # ordnungsgemäß entsorgen

Wenn Sie einen "richtigen" Mechanismus verwenden möchten, der zum "Aufräumen" nach dem Ausführen verwendet werden ChromeDriver sollte, sollten Sie diesen verwenden IWebDriver.Dispose();

Führt anwendungsdefinierte Aufgaben aus, die mit dem Freigeben, Freigeben oder Zurücksetzen nicht verwalteter Ressourcen verbunden sind. (Von IDisposable geerbt.)

Normalerweise implementiere ich eine IDisposableKlasse, mit der es zu tun hatIWebDriver

public class WebDriverController : IDisposable
{
    public IWebDriver Driver;

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

und benutze es wie:

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

Hoffe das spart dir etwas Zeit


6
Ich kann bestätigen, dass es immer noch Probleme mit dieser Strategie gibt! Ich verwende Selenium WebDriver API .NET v3.13.1.0, meine Chrome-Instanz ist auf dem neuesten Stand, ebenso wie Windows 10. Ich verwende ChromeDriver (das IDisposable durch Vererbung implementiert) wie folgt: using (var driver = new ChromeDriver()) { //my code here } Manchmal, nicht immer, "etwas" (weiß nicht was ??) passiert und chromedriver.exeist laut meinem Taskmanager immer noch unveröffentlicht.
Hauns TM

Ja, das behebt den Fehler auch nicht für mich.
Pxtl

4

Mehrere Prozesse über die Befehlszeile beenden Als Erstes müssen Sie eine Eingabeaufforderung öffnen und dann den Befehl taskkill mit der folgenden Syntax verwenden:

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

Diese Parameter beenden zwangsweise jeden Prozess, der mit dem Namen der von Ihnen angegebenen ausführbaren Datei übereinstimmt. Um beispielsweise alle Prozesse von iexplore.exe zu beenden, verwenden wir:

taskkill /F /IM iexplore.exe

Geben Sie hier die Bildbeschreibung ein


3

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

    }

und diese Funktion

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

Berufung

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

            }

Ich habe Ihren Code als letzte Bereinigung angewendet. Bisher scheint es zu funktionieren. Gut gemacht!
Exzile

2

Ich hatte das gleiche Problem beim Ausführen in Python und musste den Befehl 'killall' manuell ausführen, um alle Prozesse zu beenden. Als ich den Treiber jedoch mithilfe des Python- Kontextverwaltungsprotokolls implementierte , waren jedoch alle Prozesse weg. Es scheint, dass der Python-Interpreter wirklich gute Arbeit beim Aufräumen leistet.

Hier ist die Implementierung:

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

Und die Verwendung:

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

2

Sie können also Folgendes verwenden:

driver.close()

Schließen Sie den Browser (emuliert das Drücken der Schaltfläche zum Schließen)

driver.quit()

Beenden Sie den Browser (emuliert die Auswahl der Option zum Beenden)

driver.dispose()

Beenden Sie den Browser (versucht, jeden Tab zu schließen und dann zu beenden)

Wenn Sie jedoch NOCH auf Probleme mit hängenden Instanzen stoßen (wie ich), möchten Sie möglicherweise auch die Instanz beenden. Dazu benötigen Sie die PID der Chrome-Instanz.

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)

Wenn danach noch eine Chrominstanz übrig ist, esse ich meinen Hut. :((


2

Python-Code:

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

1

Ich weiß, dass dies eine alte Frage ist, aber ich dachte, ich würde mitteilen, was für mich funktioniert hat. Ich hatte Probleme mit Eclipse - es würde die Prozesse nicht abbrechen, und so hingen einige Phantomprozesse herum, nachdem ich den Code mit dem Eclipse-Runner getestet hatte.

Meine Lösung bestand darin, Eclipse als Administrator auszuführen. Das hat es für mich behoben. Es scheint, dass Windows Eclipse nicht erlaubt hat, den von ihm erzeugten Prozess zu schließen.


Dies ist sehr sinnvoll, aber in meinem Fall hat es nicht funktioniert und chromedriver.exebleibt in den Task-Manager-Prozessen sichtbar, unabhängig davon, ob ich Eclipse als Administrator oder normaler Benutzer starte. Es ist möglich , dass in meinem Fall das das Problem ist, da chromedriver.exeist 32 Bit und meine JRE ist 64 Bit. Eclipse Neon.1a (4.6.1), Windows 8.1 Pro 64 Bit, Java 1.8.0_92-b14.
SantiBailors

1

Ich habe das Folgende in nightwatch.js in afterEach hooks verwendet.

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

.closeWindow () schließt einfach das Fenster. (Funktioniert jedoch nicht für mehrere geöffnete Fenster). Während .end () alle verbleibenden Chrome-Prozesse beendet.


0

Ich habe dieses Problem. Ich vermute, es liegt an der Version von Serenity BDD und Selen. Der Chromedriver-Prozess wird erst freigegeben, wenn die gesamte Testsuite abgeschlossen ist. Es gibt nur 97 Tests, aber 97 Prozesse verbrauchen den Speicher eines Servers, der nicht über viele Ressourcen verfügt. Dies kann sich auf die Leistung auswirken.

Um das anzusprechen, habe ich zwei Dinge getan (dies ist spezifisch für Windows).

  1. Vor jedem Test (mit @Before kommentiert) erhalten Sie die Prozess-ID (PID) des Chromedriver-Prozesses mit:

    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. Nach jedem Test (mit @After kommentiert) töten Sie die PID mit:

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

0

Ich kam hierher und dachte anfangs, dass dies sicherlich beantwortet / gelöst worden wäre, aber nachdem ich alle Antworten gelesen hatte, war ich ein bisschen überrascht, dass niemand versuchte, alle drei Methoden zusammenzurufen:

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
}

Ich war nur hier, um nach Antworten zu suchen, und hatte nicht vor, eine zu liefern. Die obige Lösung basiert also nur auf meiner Erfahrung. Ich habe den Chrome-Treiber in einer C # -Konsolen-App verwendet und konnte die verbleibenden Prozesse erst bereinigen, nachdem alle drei Methoden zusammen aufgerufen wurden.


0

Für Ubuntu / Linux-Benutzer: - Der Befehl lautet entweder pkilloder killall. pkillwird allgemein empfohlen, da auf einigen Systemen killalltatsächlich alle Prozesse abgebrochen werden.


0

Ich benutze Protractor mit directConnect. Durch Deaktivieren der Option "--no-sandbox" wurde das Problem für mich behoben.

// 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
  • Stellen Sie sicher, dass Sie die Treiberinstanz als Singleton erhalten
  • dann am Ende anwenden
  • driver.close ()
  • driver.quit ()

Hinweis: Wenn wir jetzt den Task-Manager sehen, hängen noch keine Treiber oder Chrome-Prozesse


0

Ich habe mir alle Antworten angesehen und alle getestet. Ich habe sie alle als "Sicherheitsverschluss" zusammengefasst. Dies in c #

HINWEIS Sie können den Parameter von der IModule-App in den des tatsächlichen Treibers ändern.

 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

Beobachtet in Version 3.141.0:

Wenn Sie Ihren ChromeDriver nur mit ChromeOptions initialisieren, wird quit () chromedriver.exe nicht schließen.

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

Wenn Sie einen ChromeDriverService erstellen und übergeben, wird quit () chromedriver.exe korrekt schließen.

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

Dies ist die Lösung in Java, glaube ich. Zumindest hat es bei mir funktioniert
Isabelle T.

0

Ich benutze einfach in jedem Test eine Methode tearDown () wie folgt und ich habe überhaupt kein Problem.

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

Löschen Sie die Treiberinstanz nach dem Beenden aus dem Cache mit driver = null

Hoffe die Antwort auf die Frage


0

Es gibt einen anderen Weg, der nur für Windows funktioniert, aber jetzt ist er veraltet. Es funktioniert für frühere Selen-Versionen (es funktioniert auf Version 3.11.0).

import org.openqa.selenium.os.WindowsUtils;

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

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.