从内存中释放 Selenium chromedriver.exe

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

200404 次浏览

browser.close()将只关闭当前的铬窗口。

browser.quit()应该关闭所有打开的窗口,然后退出网络驱动程序。

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

然而 : 在我的工作场所,我们注意到在 Java 平台上执行 chromeDriver 测试时出现了一个巨大的问题,在 Java 平台上,chromedriver.exe 实际上在使用 browser.quit()之后仍然存在。为了解决这个问题,我们创建了一个类似于下面这个的批处理文件,它只是强制关闭进程。

杀死 _ 铬驱动器

@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 时。

有点奇怪,但对我很有用。我也遇到过类似的问题,在深入研究之后,我发现当我点击 WebDriver.Quit()时,浏览器中仍然有一个 UI 操作在进行(URL 加载左右)。

对我来说,解决方案(尽管非常讨厌)是在调用 exit ()之前添加一个3秒的 Sleep()

Theoretically, calling browser.Quit will close all browser tabs and kill the process.

然而,在我的情况下,我不能这样做-因为我并行运行多个测试,我不希望一个测试关闭其他窗口。因此,当我的测试结束运行时,仍然有许多“ chromedriver.exe”进程在运行。

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

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


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

我知道这是一个老问题,但我想我会分享什么工作对我来说。我在使用 Eclipse 时遇到了一些问题——它不会杀死进程,所以在使用 Eclipse 运行程序测试代码之后,我遇到了一些幻影进程。

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

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




driver.close();


driver.quit();

代码 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;
}
}
}

and this function

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
{


}

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

This answer is how to properly dispose of the driver in C#

如果你想使用一个’适当’的机制,应该用来’整理’后,运行 ChromeDriver 你应该用 IWebDriver.Dispose();

执行与释放、释放或重置非托管资源关联的应用程序定义的任务。 (Inherited from IDisposable.)

我通常在处理 IWebDriver的类上实现 IDisposable

public class WebDriverController : IDisposable
{
public IWebDriver Driver;


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

然后像这样使用它:

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

Hope this saves you some time

I have this issue. I suspect its due to the version of Serenity BDD and Selenium. The chromedriver process never releases until the entire test suite finishes. There are only 97 tests, but having 97 processes eat up the memory of a server that hasn't much resources may be having an affect on the performance.

为了解决这个问题,我做了两件事(这是针对窗口的)。

  1. 在每次测试之前(注释为@Before) ,用以下方法获得铬驱动器进程的进程 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 each test (annotated with @After) kill the PID with:

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

我来到这里,最初以为这个问题肯定会得到解决,但在阅读了所有的答案后,我有点惊讶,没有人试图把这三种方法放在一起:

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 驱动程序,只有在调用了所有三个方法之后,我才能够清理那些延迟的进程。

我在 Python 中运行它时遇到了同样的问题,我不得不手动运行“ kill all”命令来终止所有进程。但是,当我使用 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()

对于 Ubuntu/Linux 用户:- 命令是 pkillkillall。通常建议使用 pkill,因为在某些系统上,killall实际上会杀死所有进程。

我已经使用了下面的 nightwatch.jsafterEach钩子。

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

.closeWindow()只是简单地关闭窗口。(但不适用于打开多个窗口)。 Whereas .end() ends all the remaining chrome processes.

从命令行中杀死多个进程 您需要做的第一件事是打开一个命令提示符,然后使用带有以下语法的 taskkill 命令:

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

这些参数将强制终止与您指定的可执行文件名匹配的任何进程。例如,要杀死所有 iexpre.exe 进程,我们将使用:

taskkill /F /IM iexplore.exe

enter image description here

我正在使用直接连接的量角器。禁用“—— 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"]
}
},

Python 代码:

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

因此,您可以使用以下内容:

driver.close()

关闭浏览器(模拟点击关闭按钮)

driver.quit()

Quit the browser (emulates selecting the quit option)

driver.dispose()

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

However, if you are 还是 running into issues with hanging instances (as I was), you might want to also kill the instance. In order to do that, you need the PID of the chrome instance.

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)

如果在那之后还剩下一个铬实例,我就把我的帽子吃了

  • 确保驱动程序实例为 Singleton
  • 最后再申请
  • 司机 close ()
  • 司机,退出

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

我看了所有的回答,并测试了它们。我基本上把它们都编成了一个“安全关闭”。这是 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.
}
}


}

Observed on version 3.141.0:

如果只用 ChromeOptions 初始化 ChromeDriver,那么 exit ()将不会关闭 ChromeDriver.exe。

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

如果您创建并传入 ChromeDriverService,则 exit ()将正确关闭 chromedriver.exe。

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

I simply use in every test a method tearDown() as following and I have no problem at all.

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

在退出驱动程序实例之后,通过 Driver = null 将其从缓存中清除

希望能回答这个问题

还有一种方法只适用于窗口,但是现在已经不推荐了。它适用于以前的硒发行版(它适用于3.11.0版本)。

import org.openqa.selenium.os.WindowsUtils;


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

你应该申请关闭之前,而不是退出

driver.close()
driver.quit()

所以,对我来说什么都不管用。最后,我在 addArguments 上设置了一个惟一的 ID 来启动 chromeDriver,然后当我想退出时,我会这样做:

opts.addArguments(...args, 'custompid' + randomId());

然后确保它退出:

await this.driver.close()
await this.driver.quit()


spawn(`kill $(ps aux | grep ${RANDOM_PID_HERE} | grep -v "grep" | awk '{print $2}')`).on('error', e => { /* ignores when grep returns empty */ })

很难看,但这是唯一对我的案子有用的东西。

只要用这两种方式:

  • 打开控制台并运行以下命令: taskkill /F /IM chromedriver.exe /T用于终止所有铬进程
  • 在你的测试完成后,你应该 driver.Dispose,不关闭,也不退出,只是处置它。

祝你好运。

This work with python for me

import os


os.system('cmd /k "taskkill /F /IM chromedriver.exe /T"')


os.system('cmd /k "taskkill /F /IM chrome.exe /T"')

请尝试以下经过测试的代码:

ChromeDriverService driverService = ChromeDriverService.createDefaultService();
ChromeDriver chrome = new ChromeDriver(driverService, chromeOptions);
//
// code
//
//
chrome.close();
chrome.quit();
driverService.close();