从内存中释放Selenium chromedriver.exe


102

我设置了一个Python代码来运行Selenium chromedriver.exe。在运行结束时,我必须browser.close()关闭实例。(browser = webdriver.Chrome())我相信它应该chromedriver.exe从内存中释放(我在Windows 7上)。但是,每次运行后chromedriver.exe,内存中将保留一个实例。我希望有一种方法可以用python编写一些东西来杀死chromedriver.exe进程。显然browser.close()不做这项工作。谢谢。


底线...您必须以某种方式终止该过程,因为设计人员没有内置该过程。其他所有方法都可能使过程继续运行,这足以确保终止过程。
Stephen G

Answers:


73

根据Selenium API,您确实应该调用browser.quit()此方法,因为此方法将关闭所有窗口并终止进程。您仍应使用browser.quit()

但是:在我的工作场所,我们尝试在Java平台中执行chromedriver测试时注意到了一个巨大的问题,即使使用了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并不是一个庞大的程序,并且不会占用大量内存,因此您不必每次都运行它,而仅在出现问题时才运行。例如,在Eclipse中运行Project-> Clean时。


3
我不能容忍任何建议杀死进程的答案,而没有提及使进程正常结束的正确方法。如果您正确使用该quit方法,这应该不是问题。强制终止这些流程只是万不得已,您的回答应该反映出来。
JimEvans 2014年

17
看到的唯一问题是,当您调试并终止执行时,该过程仍然存在。即使单击,X它仍然保留。这是此批处理文件的唯一原因。显然quit是要走的路,但是在我的示例中,如果您调试并停止执行-它永远不会到达quit
ddavison 2014年

3
我正在回答以下问题之一:I hope there is a way I can write something to kill the chromedriver.exe process.。是的,那很好!Java不会这么做
ddavison 2014年

3
根据您使用的测试框架,如果测试的“设置”失败,您可能还会遇到幻影进程。例如,如果TestFixtureSetup方法失败,NUnit将不会调用TestFixtureTearDown方法->创建浏览器,执行一些操作,然后运行测试。如果在“您做某事”时出了点问题,那么过程就在那里。
阿兰2014年

1
如果使用DriverService接口,请保留该服务,直到完成驱动程序为止,然后也调用DriverService.stop()。对我来说,driver.quit()还不够,因为我也在使用DriverService。
金博尔·罗宾逊

38

browser.close() 将仅关闭当前的镶边窗口。

browser.quit() 应该关闭所有打开的窗口,然后退出webdriver。


9
谢谢理查德。browser.quit()确实关闭了所有打开的窗口。但是chromedriver.exe没有退出。并且有一条错误消息'InvalidURL:nonnumeric port:'port'。
KLI 2014年

5
好。我试过了browser = webdriver.Firefox()。双方browser.close()browser.quit()会关闭所有的窗口和释放内存。但是chromedriver不会这样做。
KLI 2014年

嘿,KLI。在我工作的地方,我们注意到chromedriver发生了同样的事情。这就是为什么我们有一个仅在需要时才运行的批处理文件的原因。chromedriver.exe并不是一个大过程,但是当我们尝试运行Project-> Clean时,确实会出现问题
ddavison 2014年

17

理论上,调用browser.Quit将关闭所有浏览器选项卡并终止进程。

但是,就我而言,我无法做到这一点-因为我同时运行多个测试,所以我不想使用一个测试来关闭其他窗口。因此,当我的测试完成运行时,仍有许多“ chromedriver.exe”进程正在运行。

为了克服这个问题,我编写了一个简单的清理代码(C#):

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

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

它没有帮助。该进程在Java下运行时不会被杀死
Denis Koreyba

@DenisKoreyba:我不认为实现的语言应该改变行为。在Windows操作系统上,当进程没有任何人持有时-您可以杀死它(即使它持有,也可以强制并杀死它)。您是否要在关闭浏览器选项卡后将其杀死?
伊利丹

我正在使用C#来执行此操作,我告诉java的是TeamCity的进程在其下运行。回答您的问题:是的,首先调用Dispose(),然后调用您的代码。
Denis Koreyba '16

至少在chrome驱动程序2.21版中不起作用。该进程被终止,但是控制台窗口仍然显示,可能是因为某些子进程仍然存在。aalhanane的回答如下。
Silent Sojourner '18

我将上述清理代码插入到BaseDriverClass的AssemblyCleanup部分中。如何验证chromedriver.exe进程实际上已被杀死?
僧侣

12

使用时我成功了 driver.close()之前driver.quit()。我以前只使用driver.quit()


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


driver.close();

driver.quit();

这对我不起作用。调用driver.close(); 将关闭浏览器并将驱动程序设置为null。然后就没有必要调用driver.quit();了。因为它将抛出空异常。
Priyanka

该实现对当前硒有一些更改,如果进程被杀死,则可能不需要quit()。确保执行此操作时,任务管理器不应被杀死浏览器进程。
Shantonu

7

有点奇怪,但对我有用。我遇到了类似的问题,经过一番挖掘后,我发现当我点击时,浏览器中仍在进行UI操作(URL加载等)WebDriver.Quit()

对我来说,解决方案(虽然非常讨厌)是Sleep()在调用Quit()之前添加了3秒。


3
谢谢,这实际上也为我工作。我以前也使用WebDriver.Quit()过,但是有时它使一个chrome.exe进程还活着。另外,我猜这并不是在所有操作系统上都发生。
Grengas

1
这也对我有用!它可能会让您感到有点脏,但有时会出现随机的Thread.Sleeps似乎是医生为UI测试所订购的。
Dan Csharpster,

对我而言,自行关闭或自行退出也使驱动程序落后。两者都很好地清理了。
马克·鲍尔

大!这也对我有用。我添加了Task.Delay(TimeSpan.FromSeconds(3)); 调用driver.Quit()之前,它将关闭所有chromedriver.exe文件
Priyanka

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
我可以确认此策略仍然存在问题!我使用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()

退出浏览器(尝试关闭每个选项卡,然后退出)

但是,如果仍然遇到挂起实例的问题(就像我以前一样),则可能还想杀死该实例。为此,您需要Chrome实例的PID。

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)

如果那之后还有一个Chrome实例,我会吃掉我的帽子。:(



1

我知道这有点老了,但我想我会分享对我有用的东西。我在使用Eclipse时遇到问题-它不会杀死进程,因此在使用Eclipse运行器测试代码后,我周围有一堆幻影进程。

我的解决方案是以管理员身份运行Eclipse。这为我解决了。似乎Windows不允许Eclipse关闭它产生的进程。


这很有意义,但是就我而言,它chromedriver.exe不管用,无论我以管理员身份还是普通用户身份启动Eclipse,在Task Manager进程中仍然可见。就我而言,可能是问题所在,因为它chromedriver.exe是32位,而我的JRE是64位。Eclipse Neon.1a(4.6.1),Windows 8.1 Pro 64位,Java 1.8.0_92-b14。
SantiBailors,2016年

1

我在afterEach挂钩中的nightwatch.js中使用了以下内容。

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个进程消耗了没有太多资源的服务器的内存,这可能会影响性能。

为了解决我做了两件事(这是特定于Windows的)。

  1. 在每个测试(用@Before注释)之前,使用以下命令获取chromedriver进程的进程ID(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
}

我只是在这里寻找答案,并不打算提供答案。因此,上述解决方案仅基于我的经验。我在C#控制台应用程序中使用了chrome驱动程序,只有在一起调用所有这三种方法后,我才能清理残留的进程。


0

对于Ubuntu / Linux用户:-命令为pkillkillallpkill通常建议您这样做,因为在某些系统上,它killall实际上会杀死所有进程。


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
  • 确保您将Driver实例获取为Singleton
  • 然后最后申请
  • driver.close()
  • driver.quit()

注意:现在,如果我们看到任务管理器,您将找不到任何驱动程序或chrome进程仍挂起


0

我查看了所有回复并测试了所有回复。我几乎将它们全部编译为一个“安全关闭”。这在C#中

注意您可以将参数从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.
        }
    }

}

0

在3.141.0版本上观察到:

如果仅使用ChromeOptions初始化ChromeDriver,则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()

我相信这是Java中的解决方案。至少,它为我工作
伊莎贝尔T.

0

我只是在每个测试中都使用如下方法tearDown(),我一点都没有问题。

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

退出驱动程序实例后,通过driver = null从缓存中清除它

希望回答问题


0

还有另一种方法仅适用于Windows,但现在已弃用。它适用于早期的硒版本(适用于3.11.0版本)。

import org.openqa.selenium.os.WindowsUtils;

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

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.