освободить Selenium chromedriver.exe из памяти

104

Я установил код Python для запуска Selenium chromedriver.exe. В конце пробега я должен browser.close()закрыть экземпляр. ( browser = webdriver.Chrome()) Я считаю, что он должен освободиться chromedriver.exeпо памяти (у меня Windows 7). Однако после каждого запуска chromedriver.exeв памяти остается один экземпляр. Я надеюсь, что есть способ написать что-нибудь на Python, чтобы убить chromedriver.exeпроцесс. Очевидно browser.close(), не работает. Спасибо.

KLI
источник
Итог ... вы должны каким-то образом убить процесс, потому что разработчики его не встроили. Все другие способы могут оставить процесс запущенным, и этого достаточно, чтобы убить.
Стивен Дж.

Ответы:

74

согласно Selenium API, вам действительно следует вызвать, browser.quit()поскольку этот метод закроет все окна и завершит процесс. Вы все равно должны использовать browser.quit().

Однако : на моем рабочем месте мы заметили огромную проблему при попытке выполнить тесты chromedriver на платформе Java, где chromedriver.exe фактически все еще существует даже после использования browser.quit(). Чтобы противостоять этому, мы создали командный файл, подобный приведенному ниже, который просто принудительно закрывает процессы.

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

Поскольку chromedriver.exe не является большой программой и не потребляет много памяти, вам не нужно запускать ее каждый раз, а только тогда, когда она представляет проблему. Например, при запуске Project-> Clean в Eclipse.

Дэвисон
источник
3
Я не могу оправдать любой ответ, который рекомендует убивать процессы, не упомянув также о правильном способе нормального завершения этих процессов. Если вы правильно используете quitметод, это не должно быть проблемой. Насильственное уничтожение процессов должно быть только крайней мерой, и ваш ответ должен это отражать.
JimEvans
17
Обратите внимание на единственную проблему: когда вы отлаживаете и прерываете выполнение, процесс все равно остается. Даже если вы нажмете кнопку, Xона все равно останется. это ЕДИНСТВЕННАЯ причина для этого командного файла. Очевидно, quitэто правильный путь, однако в моем примере, если вы отлаживаете и останавливаете выполнение - он никогда не достигает quit.
ddavison
3
Я отвечаю на один из вопросов: I hope there is a way I can write something to kill the chromedriver.exe process.. и да, это приятно! Java этого не делает
ddavison
3
В зависимости от используемой вами тестовой среды, вы также можете столкнуться с фантомными процессами, если тесты не пройдут его «настройку». NUnit, например, не будет вызывать метод TestFixtureTearDown, если что-то в методе TestFixtureSetup завершится неудачно -> вы создаете браузер, выполняете некоторые действия, а затем запускаете тест. Если что-то пойдет не так, когда «ты делаешь что-то», то все, процесс остается.
Arran
1
Если вы используете интерфейс DriverService, удерживайте службу, пока не закончите работу с драйвером, а также вызовите DriverService.stop (). Для меня driver.quit () было недостаточно, потому что я также использовал DriverService.
Кимбалл Робинсон,
39

browser.close() закроет только текущее окно Chrome.

browser.quit() должен закрыть все открытые окна, а затем выйти из webdriver.

Ричард
источник
9
Спасибо, Ричард. browser.quit()закрыл все открытые окна. Но chromedriver.exe не был закрыт. И появилось сообщение об ошибке InvalidURL: nonnumeric port: 'port' '.
KLI
5
ХОРОШО. Я пробовал browser = webdriver.Firefox(). Оба browser.close()и browser.quit()закроют все окна и освободят память. Однако хромодрайвер не сделал бы того же.
KLI
Привет, KLI. Здесь, где я работаю, мы заметили те же самые вещи, происходящие с хромодрайвером. Вот почему у нас есть командный файл, который мы запускаем только тогда, когда нам нужно. chromedriver.exe - небольшой процесс, но он представляет проблему, когда мы пытаемся запустить Project-> Clean, например
ddavison
17

Теоретически вызов browser.Quit закроет все вкладки браузера и убьет процесс.

Однако в моем случае я не смог этого сделать - поскольку я запускал несколько тестов параллельно, я не хотел, чтобы один тест закрыл окна для других. Поэтому, когда мои тесты заканчиваются, остается много запущенных процессов "chromedriver.exe".

Чтобы преодолеть это, я написал простой код очистки (C #):

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

foreach(var chromeDriverProcess in chromeDriverProcesses)
{
     chromeDriverProcess.Kill();
}
Иллидан
источник
Это не помогло. Процесс не убивается при запуске под java
Денис Корейба 08
@DenisKoreyba: Я не думаю, что язык реализации должен менять поведение. В ОС Windows, когда процесс никем не удерживается - вы можете убить его (даже если он удерживается, вы можете принудительно убить его). Вы пытаетесь убить его после закрытия вкладок браузера?
Illidan
Я использую C # для этого, о java я сказал, что процесс TeamCity запускается под ним. Отвечая на ваш вопрос: да, сначала я вызываю Dispose (), а затем ваш код.
Денис Корейба 09
Это не работает с драйвером Chrome, по крайней мере, версии 2.21. Процесс завершен, но окно консоли все еще отображается, вероятно, потому, что какой-то дочерний процесс все еще существует. Ответ aalhanane ниже работает.
Silent Sojourner
Я вставил вышеупомянутый код очистки в раздел AssemblyCleanup класса BaseDriverClass. Как я могу убедиться, что процесс chromedriver.exe действительно был убит?
monkrus
13
//Calling close and then quit will kill the driver running process.


driver.close();

driver.quit();
Шантону
источник
У меня это не сработало. Вызов driver.close (); закроет браузер и установит для драйвера значение null. И тогда нет смысла вызывать driver.quit (); так как это вызовет нулевое исключение.
Приянка
реализация имеет некоторые изменения в текущем селене, вам может не понадобиться quit (), если процесс убит. Убедитесь, что при этом ваш диспетчер задач не должен убивать процесс браузера.
Шантону
12

У меня был успех при использовании driver.close()раньше driver.quit(). Раньше я только использовал driver.quit().

королевская шляпа
источник
7

Это как-то странно, но у меня это работает. У меня была аналогичная проблема, после некоторого рытья я обнаружил, что в браузере все еще происходит действие пользовательского интерфейса (загрузка URL-адреса или около того), когда я нажимаю WebDriver.Quit().

Решение для меня (хотя и очень неприятное) заключалось в том, чтобы добавить Sleep()3 секунды перед вызовом Quit ().

Альпана Чаухан
источник
3
Спасибо, у меня тоже это сработало. Я использовал то WebDriver.Quit()же самое раньше, но иногда оставался один процесс chrome.exe живым. Также я предполагаю, что это происходит не во всех операционных системах.
Grengas 03 авг.15,
1
У меня это тоже сработало! Это может заставить вас почувствовать себя немного грязным, но иногда случайный поток Thread.Sleep кажется тем, что доктор прописал для тестов пользовательского интерфейса.
Дэн Чарпстер
То же самое для меня, закрыть или выйти самостоятельно, оставив процесс драйвера позади. И то, и другое хорошо убрано.
Марк Болл
Большой! У меня это тоже сработало. Я добавил Task.Delay (TimeSpan.FromSeconds (3)); перед вызовом driver.Quit (), и он закрывает все файлы chromedriver.exe
Приянка
5

Этот ответ - как правильно избавиться от драйвера в C #.

Если вы хотите использовать «правильный» механизм, который следует использовать для «уборки» после запуска, ChromeDriver вы должны использовать IWebDriver.Dispose();

Выполняет определяемые приложением задачи, связанные с освобождением, освобождением или сбросом неуправляемых ресурсов. (Унаследовано от IDisposable.)

Я обычно использую IDisposableкласс, который имеет дело сIWebDriver

public class WebDriverController : IDisposable
{
    public IWebDriver Driver;

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

и используйте его как:

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

Надеюсь, это сэкономит вам время

Матас Вайткявичюс
источник
6
Могу подтвердить, что с этой стратегией все еще есть проблемы! Я использую Selenium WebDriver API .NET v3.13.1.0, мой экземпляр Chrome обновлен, как и моя Windows 10 ... Я использую ChromeDriver (который реализует IDisposable по наследству) следующим образом: using (var driver = new ChromeDriver()) { //my code here } Иногда, не всегда, "что-то" (не знаю, что ??) происходит и chromedriver.exe, согласно моему диспетчеру задач, до сих пор не выпущено.
Hauns TM
Да, это тоже не исправляет ошибку.
Pxtl
4

Завершение нескольких процессов из командной строки Первое, что вам нужно сделать, это открыть командную строку, а затем использовать команду taskkill со следующим синтаксисом:

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

Эти параметры принудительно завершат любой процесс, соответствующий имени указанного исполняемого файла. Например, чтобы убить все процессы iexplore.exe, мы будем использовать:

taskkill /F /IM iexplore.exe

введите описание изображения здесь

Сумит Кумар Прадхан
источник
3

Код c #

с помощью System.Diagnostics;

с помощью 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;
            }
        }

    }

и эта функция

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

Вызов

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

            }
алханан
источник
Я применил ваш код в качестве последней очистки. Пока вроде работает. Хорошая работа!
Exzile
2

У меня была такая же проблема при запуске на Python, и мне пришлось вручную запустить команду killall, чтобы убить все процессы. Однако, когда я реализовал драйвер с использованием протокола управления контекстом Python , все процессы пропали. Кажется, что интерпретатор Python действительно хорошо помогает навести порядок.

Вот реализация:

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

И использование:

with Browser() as browser:
    browser.navigate_to_page()
Волшебник
источник
2

Итак, вы можете использовать следующее:

driver.close()

Закройте браузер (имитирует нажатие кнопки закрытия)

driver.quit()

Закройте браузер (имитирует выбор варианта выхода)

driver.dispose()

Закройте браузер (пытается закрыть все вкладки, затем выйдите)

Однако, если вы STILL нарваться проблемы с висящими экземплярами (как я), вы можете также убить экземпляр. Для этого вам понадобится PID экземпляра 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)

Если после этого останется хромированный экземпляр, я съем шляпу. :(

Rue Lazzaro
источник
2

Код Python:

try:
    # do my automated tasks
except:
    pass
finally:
    driver.close()
    driver.quit()
Моше Славин
источник
1

Я знаю, что это старый вопрос, но я подумал, что поделюсь тем, что сработало для меня. У меня были проблемы с Eclipse - он не убивал процессы, поэтому после тестирования кода с помощью Eclipse runner у меня оставалась куча фантомных процессов.

Моим решением было запустить Eclipse от имени администратора. Это исправило это для меня. Похоже, Windows не позволяла Eclipse закрывать порожденный им процесс.

Forresthopkinsa
источник
Это имеет большой смысл, но в моем случае это не сработало, chromedriver.exeостается видимым среди процессов диспетчера задач, независимо от того, запускаю я Eclipse как администратор или обычный пользователь. Возможно, что в моем случае это проблема, потому что chromedriver.exeон 32-битный, а моя JRE - 64-битная. Eclipse Neon.1a (4.6.1), 64-разрядная версия Windows 8.1 Pro, Java 1.8.0_92-b14.
SantiBailors
1

Я использовал нижеприведенное в nightwatch.js в хуках afterEach.

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

.closeWindow () просто закрывает окно. (Но не работает для нескольких открытых окон). В то время как .end () завершает все оставшиеся процессы Chrome.

Саймон Коррейя
источник
0

У меня такая проблема. Я подозреваю, что это связано с версией Serenity BDD и Selenium. Процесс chromedriver никогда не запускается, пока не завершится весь набор тестов. Всего 97 тестов, но 97 процессов занимают память сервера, у которого мало ресурсов, что может повлиять на производительность.

Для решения этой проблемы я сделал 2 вещи (это относится к окнам).

  1. перед каждым тестом (помеченным @Before) получите идентификатор процесса (PID) процесса хромированного драйвера с помощью:

    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. после каждого теста (помеченного @After) убейте PID с помощью:

    Runtime.getRuntime().exec("taskkill /F /PID " + pid);
    
Дин Макнабб
источник
0

Сначала я пришел сюда, думая, что на этот вопрос можно будет ответить / решить, но после прочтения всех ответов я был немного удивлен, что никто не попытался вызвать все три метода вместе:

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
}

Я был здесь только для того, чтобы искать ответы, и не собирался их давать. Таким образом, приведенное выше решение основано только на моем опыте. Я использовал драйвер Chrome в консольном приложении C # и смог очистить устаревшие процессы только после одновременного вызова всех трех методов.

Луи Бао
источник
0

Для пользователей Ubuntu / Linux: - команда либо pkillили killall. pkillобычно рекомендуется, так как в некоторых системах killallфактически убивает все процессы.

Manmohan_singh
источник
0

Я использую транспортир с directConnect. Отключение параметра «--no-sandbox» устранило проблему для меня.

// 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
  • Убедитесь, что вы получаете экземпляр драйвера как Singleton
  • затем Применить в конце
  • driver.close ()
  • driver.quit ()

Примечание: теперь, если мы видим диспетчер задач, вы не обнаружите, что какой-либо драйвер или процесс Chrome все еще висят.

Сара
источник
0

Я просмотрел все ответы и все их протестировал. Я в значительной степени собрал их все в один как «Защитное закрытие». Это в С #

ПРИМЕЧАНИЕ. Вы можете изменить параметр из приложения IModule на параметр реального драйвера.

 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
источник
0

Наблюдается на версии 3.141.0:

Если вы инициализируете ChromeDriver только с помощью ChromeOptions, quit () не закроет chromedriver.exe.

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

Если вы создадите и передадите ChromeDriverService, quit () правильно закроет chromedriver.exe.

    ChromeDriverService driverService = ChromeDriverService.CreateDefaultService();
    ChromeOptions chromeOptions = new ChromeOptions();
    ChromeDriver driver = new ChromeDriver(driverService, chromeOptions);
    // .. do stuff ..
    driver.quit()
Vhoang
источник
Я считаю, что это решение на Java. По крайней мере, у меня это сработало
Изабель Т.
0

Я просто использую в каждом тесте метод tearDown (), как показано ниже, и у меня нет никаких проблем.

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

После выхода из экземпляра драйвера очистите его из кеша с помощью driver = null

Надеюсь ответ на вопрос

Джамиль
источник
0

Есть еще один способ, который работает только для окон, но теперь он устарел. он работает для предыдущих выпусков селена (работает в версии 3.11.0).

import org.openqa.selenium.os.WindowsUtils;

 WindowsUtils.killByName("chromedriver.exe") // any process name you want
Норайр Саргсян
источник
0

Вы должны подать заявку, прежде чем выйти

driver.close()
driver.quit()
Сара Бурая
источник
1
--Редактировать -> Удален "driver.close ()", и все заработало
Педро Хоакин