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.

KLI
quelle
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
Wie töte ich den Chrome-Treiberprozessor mithilfe von Selen? Schauen Sie sich dieses einfache Beispiel an.
Sumit Kumar Pradhan

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.

ddavison
quelle
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.

Richard
quelle
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();
}
Illidan
quelle
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().

Königshut
quelle
12
//Calling close and then quit will kill the driver running process.


driver.close();

driver.quit();
Shantonu
quelle
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 .

Alpana Chauhan
quelle
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

Matas Vaitkevicius
quelle
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

Sumit Kumar Pradhan
quelle
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
            {

            }
Aalhanan
quelle
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()
Magier
quelle
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. :((

Rue Lazzaro
quelle
2

Python-Code:

try:
    # do my automated tasks
except:
    pass
finally:
    driver.close()
    driver.quit()
Moshe Slavin
quelle
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.

forresthopkinsa
quelle
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.

Simon Correia
quelle
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);
    
Dean McNabb
quelle
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.

Louie Bao
quelle
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.

Manmohan_singh
quelle
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"]
  }
},
Georgi Ekimov
quelle
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

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

}
Exzile
quelle
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()
vhoang
quelle
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

Jamil
quelle
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
Norayr Sargsyan
quelle
0

Sie sollten sich kurz vor dem Beenden bewerben

driver.close()
driver.quit()
Sara Bouraya
quelle
Funktioniert nicht, chromedriver.exe noch geöffnet
Pedro Joaquín
1
--Edit -> "driver.close ()" entfernt und es hat funktioniert
Pedro Joaquín