zwolnij Selenium chromedriver.exe z pamięci


102

Skonfigurowałem kod Pythona, aby uruchomić Selenium chromedriver.exe. Pod koniec biegu muszę browser.close()zamknąć instancję. ( browser = webdriver.Chrome()) Uważam, że powinien zwolnić się chromedriver.exez pamięci (pracuję na Windows 7). Jednak po każdym uruchomieniu chromedriver.exew pamięci pozostaje jedna instancja. Mam nadzieję, że jest sposób, w jaki mogę napisać coś w Pythonie, aby zabić chromedriver.exeproces. Oczywiście browser.close()nie działa. Dzięki.


Podsumowując ... musisz jakoś zabić proces, ponieważ projektanci go nie wbudowali. Wszystkie inne sposoby mogą spowodować, że proces będzie działał i to wystarczy, aby zabić.
Stephen G

Odpowiedzi:


73

zgodnie z API Selenium, naprawdę powinieneś wywołać, browser.quit()ponieważ ta metoda zamknie wszystkie okna i zabije proces. Nadal powinieneś używać browser.quit().

Jednak : w moim miejscu pracy zauważyliśmy ogromny problem podczas próby wykonania testów chromedriver na platformie Java, gdzie plik chromedriver.exe nadal istnieje nawet po użyciu browser.quit(). Aby temu przeciwdziałać, stworzyliśmy plik wsadowy podobny do tego poniżej, który po prostu wymusza zamknięcie procesów.

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

Ponieważ chromedriver.exe nie jest dużym programem i nie zużywa dużo pamięci, nie powinieneś go uruchamiać za każdym razem, ale tylko wtedy, gdy stwarza problem. Na przykład podczas uruchamiania Project-> Clean in Eclipse.


3
Nie mogę zaakceptować żadnej odpowiedzi, która zaleca zabijanie procesów, nie wspominając również o prawidłowym sposobie normalnego zakończenia tych procesów. Jeśli prawidłowo zastosujesz tę quitmetodę, nie powinno to stanowić problemu. Zabijanie procesów na siłę powinno być tylko ostatecznością, a twoja odpowiedź powinna to odzwierciedlać.
JimEvans,

17
Zobacz jedyny problem z tym, że kiedy debugujesz i zabijasz wykonanie - proces nadal pozostaje. Nawet jeśli klikniesz X, nadal pozostaje. to JEDYNY powód dla tego pliku wsadowego. Oczywiście quitjest to droga do zrobienia, jednak w moim przykładzie, jeśli debugujesz i zatrzymasz wykonywanie - nigdy nie osiągnie quit.
ddavison

3
Jestem odpowiadając na jedno z pytań: I hope there is a way I can write something to kill the chromedriver.exe process.. i tak, to jest miłe! Java tego nie robi
ddavison

3
W zależności od używanego środowiska testowego, możesz również skończyć z procesami pozornymi, jeśli testy zawiodą w ich „konfiguracji”. Na przykład NUnit nie wywoła metody TestFixtureTearDown, jeśli coś się nie powiedzie w metodzie TestFixtureSetup -> tworzysz przeglądarkę, robisz coś, a następnie uruchamiasz test. Jeśli coś pójdzie nie tak, gdy „coś robisz”, to wszystko. Proces tam pozostaje.
Arran

1
Jeśli korzystasz z interfejsu DriverService, przytrzymaj usługę do czasu zakończenia pracy ze sterownikiem i wywołaj również DriverService.stop (). Dla mnie driver.quit () nie był wystarczający, ponieważ używałem również DriverService.
Kimball Robinson,

38

browser.close() zamknie tylko bieżące okno chrome.

browser.quit() powinien zamknąć wszystkie otwarte okna, a następnie zamknąć sterownik sieciowy.


9
Dzięki Richard. browser.quit()zamknął wszystkie otwarte okna. Ale chromedriver.exe nie został zamknięty. Pojawił się komunikat o błędzie „Nieprawidłowy adres URL: nieliczbowy port:„ port ””.
KLI

5
DOBRZE. Próbowałem browser = webdriver.Firefox(). Obie browser.close()i browser.quit()zamkną wszystkie okna i zwolnią pamięć. Jednak chromedriver nie zrobiłby tego samego.
KLI

Hej, KLI. Tutaj, gdzie pracuję, zauważyliśmy dokładnie to samo, co dzieje się z chromedriver. Dlatego mamy plik wsadowy, który uruchamiamy tylko wtedy, gdy jest to konieczne. chromedriver.exe nie jest dużym procesem, ale stwarza problem, gdy próbujemy na przykład uruchomić Project-> Clean
ddavison

17

Teoretycznie wywołanie browser.Quit zamknie wszystkie karty przeglądarki i zakończy proces.

Jednak w moim przypadku nie byłem w stanie tego zrobić - skoro równolegle prowadziłem wiele testów, nie chciałem, aby jeden test zamykał okna dla innych. Dlatego po zakończeniu testów nadal działa wiele procesów „chromedriver.exe”.

Aby temu zaradzić, napisałem prosty kod porządkujący (C #):

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

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

To nie pomogło. Proces nie jest
przerywany,

@DenisKoreyba: Nie sądzę, że język implementacji powinien zmieniać zachowanie. W systemie operacyjnym Windows, gdy proces nie jest przez nikogo utrzymywany - możesz go zabić (nawet jeśli został wstrzymany, możesz go wymusić i zabić). Czy próbujesz go zabić po zamknięciu kart przeglądarki?
Illidan,

Używam C # do tego, co powiedziałem o javie to, że proces TeamCity jest uruchamiany pod nim. Odpowiadając na twoje pytanie: tak, najpierw wywołuję Dispose (), a następnie twój kod.
Denis Koreyba

To nie działa na sterowniku Chrome w wersji co najmniej 2.21. Proces zostaje zabity, ale okno konsoli nadal jest wyświetlane, prawdopodobnie dlatego, że nadal istnieje jakiś proces potomny. Odpowiedź aalhanane poniżej działa.
Silent Sojourner

Wstawiłem wyżej wymieniony kod czyszczenia do sekcji AssemblyCleanup w BaseDriverClass. Jak mogę sprawdzić, czy proces chromedriver.exe został faktycznie zabity?
monkrus

12

Miałem sukces, używając driver.close()wcześniej driver.quit(). Wcześniej używałem tylko driver.quit().


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


driver.close();

driver.quit();

To nie zadziałało dla mnie. Wywołanie driver.close (); zamknie przeglądarkę i ustawi sterownik na null. A potem nie ma sensu wywoływać driver.quit (); ponieważ zgłosi wyjątek zerowy.
Priyanka

implementacja ma pewne zmiany w obecnym selenie, możesz nie potrzebować quit (), jeśli proces zostanie zabity. Upewnij się, że kiedy to zrobisz, twój menedżer zadań nie powinien zabić procesu przeglądarki.
Shantonu

7

To trochę dziwne, ale dla mnie działa. Miałem podobny problem, po pewnym kopaniu odkryłem, że w przeglądarce nadal trwa akcja interfejsu użytkownika (ładowanie adresu URL lub coś podobnego), kiedy trafiłemWebDriver.Quit() .

Rozwiązaniem dla mnie (choć bardzo paskudnym) było dodanie Sleep()3 sekund przed wywołaniem Quit ().


3
Dzięki, dla mnie to też zadziałało. Używałem WebDriver.Quit()również wcześniej, ale czasami było to pozostawiając jeden proces chrome.exe żyje. Wydaje mi się, że nie dzieje się to we wszystkich systemach operacyjnych.
Grengas

1
U mnie też to zadziałało! Może to sprawić, że poczujesz się trochę brudny, ale czasami przypadkowe Wątki wydają się być tym, co lekarz zalecił do testów UI.
Dan Csharpster

To samo dotyczy mnie, zamyka się samodzielnie lub wyłącza się samodzielnie, pozostawiając proces sterownika za sobą. Oba ładnie posprzątałem.
Mark Ball

Wspaniały! Dla mnie to też zadziałało. Dodałem Task.Delay (TimeSpan.FromSeconds (3)); przed wywołaniem driver.Quit () i zamyka wszystkie pliki chromedriver.exe
Priyanka

5

Ta odpowiedź brzmi, jak prawidłowo pozbyć się sterownika w C #

Jeśli chcesz użyć „właściwego” mechanizmu, którego należy użyć do „uporządkowania” po uruchomieniu ChromeDriver , powinieneś użyć IWebDriver.Dispose();

Wykonuje zdefiniowane przez aplikację zadania związane ze zwalnianiem, zwalnianiem lub resetowaniem niezarządzanych zasobów. (Odziedziczone po IDisposable.)

Zwykle wdrażam IDisposablena zajęciach, z którymi mam do czynieniaIWebDriver

public class WebDriverController : IDisposable
{
    public IWebDriver Driver;

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

i używaj go jak:

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

Mam nadzieję, że zaoszczędzi ci to trochę czasu


6
Mogę potwierdzić, że nadal są problemy z tą strategią! Używam Selenium WebDriver API .NET v3.13.1.0, moja instancja Chrome jest aktualna, podobnie jak mój Windows 10 ... Używam ChromeDriver (który implementuje IDisposable przez dziedziczenie) w następujący sposób: using (var driver = new ChromeDriver()) { //my code here } Czasami, nie zawsze, „coś” (nie wiem co ??) dzieje się i chromedriver.exewedług mojego menedżera zadań nadal nie zostało wydane.
Hauns TM,

Tak, to też nie naprawia błędu.
Pxtl

4

Zabij wiele procesów z wiersza poleceń Pierwszą rzeczą, którą musisz zrobić, to otworzyć wiersz polecenia, a następnie użyć polecenia taskkill z następującą składnią:

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

Te parametry wymuszą zabicie każdego procesu pasującego do nazwy pliku wykonywalnego, który określisz. Na przykład, aby zabić wszystkie procesy iexplore.exe, użylibyśmy:

taskkill /F /IM iexplore.exe

wprowadź opis obrazu tutaj


3

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

    }

i ta funkcja

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

Powołanie

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

            }

Zastosowałem twój kod jako ostateczne oczyszczenie. Jak dotąd wydaje się, że działa. Dobra robota!
Exzile

2

Miałem ten sam problem podczas uruchamiania go w Pythonie i musiałem ręcznie uruchomić polecenie „killall”, aby zabić wszystkie procesy. Jednak kiedy zaimplementowałem sterownik przy użyciu protokołu zarządzania kontekstem Pythona wszystkie procesy zniknęły. Wygląda na to, że interpreter Pythona naprawdę dobrze radzi sobie z porządkowaniem rzeczy.

Oto realizacja:

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

I użycie:

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

2

Możesz więc użyć następujących:

driver.close()

Zamknij przeglądarkę (emuluje naciśnięcie przycisku zamykania)

driver.quit()

Zamknij przeglądarkę (emuluje wybranie opcji wyjścia)

driver.dispose()

Zamknij przeglądarkę (próbuje zamknąć każdą kartę, a następnie zamknij)

Jeśli jednak NADAL masz problemy z zawieszonymi instancjami (tak jak ja), możesz również chcieć zabić instancję. Aby to zrobić, potrzebujesz PID instancji 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)

Jeśli po tym pozostanie chromowana instancja, zjem kapelusz. :(


2

Kod Pythona:

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

1

Wiem, że jest to trochę stare pytanie, ale pomyślałem, że podzielę się tym, co zadziałało. Miałem problemy z Eclipse - nie zabijało to procesów, więc po przetestowaniu kodu przy użyciu Eclipse runner kręciło się kilka procesów fantomowych.

Moim rozwiązaniem było uruchomienie Eclipse jako administrator. To naprawiło to dla mnie. Wygląda na to, że system Windows nie pozwolił Eclipse na zamknięcie uruchomionego procesu.


Ma to sens, ale w moim przypadku nie zadziałało, chromedriver.exepozostaje widoczne wśród procesów Menedżera zadań bez względu na to, czy uruchamiam Eclipse jako administrator czy zwykły użytkownik. Jest możliwe, że w moim przypadku to jest problem, bo chromedriver.exejest 32 bitowy i mój JRE jest 64-bitowy. Eclipse Neon.1a (4.6.1), Windows 8.1 Pro w wersji 64-bitowej, Java 1.8.0_92-b14.
SantiBailors

1

Użyłem poniższego w nightwatch.js w afterEach hooków.

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

.closeWindow () po prostu zamyka okno. (Ale nie będzie działać dla wielu otwartych okien). Natomiast .end () kończy wszystkie pozostałe procesy chrome.


0

Mam ten problem. Podejrzewam, że jest to spowodowane wersją Serenity BDD i Selenium. Proces chromedriver nigdy nie jest zwalniany, dopóki cały zestaw testów nie zostanie zakończony. Jest tylko 97 testów, ale fakt, że 97 procesów pochłania pamięć serwera, który nie ma zbyt wielu zasobów, może mieć wpływ na wydajność.

Aby rozwiązać problem, zrobiłem 2 rzeczy (jest to specyficzne dla systemu Windows).

  1. przed każdym testem (z adnotacją @Before) pobierz identyfikator procesu (PID) procesu chromedriver z:

    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. po każdym teście (z adnotacją @After) zabij PID za pomocą:

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

0

Przyszedłem tutaj początkowo myśląc, że z pewnością byłoby to odpowiedź / rozwiązane, ale po przeczytaniu wszystkich odpowiedzi byłem nieco zaskoczony, że nikt nie próbował połączyć wszystkich trzech metod razem:

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
}

Byłem tu tylko po to, by szukać odpowiedzi i nie zamierzałem ich udzielać. Zatem powyższe rozwiązanie bazuje wyłącznie na moim doświadczeniu. Używałem sterownika Chrome w aplikacji konsolowej C # i udało mi się wyczyścić utrzymujące się procesy dopiero po wywołaniu wszystkich trzech metod razem.


0

Dla użytkowników Ubuntu / Linux: - komenda jest albo pkillalbo killall. pkilljest ogólnie zalecany, ponieważ w niektórych systemach killallfaktycznie zabija wszystkie procesy.


0

Używam Protractor z directConnect. Wyłączenie opcji „--no-sandbox” rozwiązało problem.

// 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
  • Upewnij się, że otrzymujesz instancję sterownika jako Singleton
  • następnie Zastosuj na końcu
  • driver.close ()
  • driver.quit ()

Uwaga: teraz, jeśli zobaczymy menedżera zadań, nie znajdziesz żadnego sterownika ani procesu chrome, który nadal się zawiesił


0

Przejrzałem wszystkie odpowiedzi i przetestowałem je wszystkie. Prawie zebrałem je wszystkie w jeden jako „Zamknięcie bezpieczeństwa”. To w c #

UWAGA, możesz zmienić parametr z aplikacji IModule na parametr aktualnego sterownika.

 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

Obserwowane w wersji 3.141.0:

Jeśli zainicjujesz ChromeDriver tylko przy użyciu ChromeOptions, quit () nie zamknie chromedriver.exe.

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

Jeśli utworzysz i przekażesz usługę ChromeDriverService, quit () zamknie poprawnie plik chromedriver.exe.

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

Uważam, że to jest rozwiązanie w Javie. Przynajmniej mi się udało
Isabelle T.

0

Po prostu używam w każdym teście metody tearDown () jak następuje i nie mam żadnego problemu.

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

Po zamknięciu instancji sterownika wyczyść ją z pamięci podręcznej przez driver = null

Mam nadzieję, że odpowiem na pytanie


0

Jest inny sposób, który działa tylko w systemie Windows, ale teraz jest przestarzały. działa z wcześniejszymi wersjami selenu (działa z wersją 3.11.0).

import org.openqa.selenium.os.WindowsUtils;

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

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.