liberar Selenium chromedriver.exe da memória

102

Eu configurei um código python para executar o Selenium chromedriver.exe. No final da execução, tenho browser.close()que fechar a instância. ( browser = webdriver.Chrome()) Acredito que deveria liberar chromedriver.exeda memória (estou no Windows 7). No entanto, após cada execução, uma chromedriver.exeinstância permanece na memória. Espero que haja uma maneira de escrever algo em python para encerrar o chromedriver.exeprocesso. Obviamente browser.close(), não faz o trabalho. Obrigado.

KLI
fonte
Resumindo ... você tem que interromper o processo de alguma forma porque os designers não o incorporaram. Todas as outras maneiras podem deixar um processo em execução e isso é o suficiente para justificar a morte.
Stephen G de
Como eu mato o processador de driver do Chrome usando Selenium, verifique este exemplo simples.
sumit kumar pradhan

Respostas:

73

pela API Selenium, você realmente deve chamar, browser.quit()pois esse método fechará todas as janelas e encerrará o processo. Você ainda deve usar browser.quit().

No entanto : Em meu local de trabalho, notamos um grande problema ao tentar executar testes de chromedriver na plataforma Java, onde o chromedriver.exe realmente ainda existe mesmo após o uso browser.quit(). Para evitar isso, criamos um arquivo batch semelhante a este abaixo, que apenas força o fechamento dos processos.

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

Como o chromedriver.exe não é um programa muito grande e não consome muita memória, você não deve ter que executá-lo todas as vezes, mas apenas quando apresentar um problema. Por exemplo, ao executar Projeto-> Limpar no Eclipse.

ddavison
fonte
3
Não posso tolerar qualquer resposta que recomende eliminar processos sem também mencionar a maneira correta de fazer com que esses processos terminem normalmente. Se você usar o quitmétodo corretamente , isso não deve ser um problema. Eliminar os processos à força deve ser apenas o último recurso, e sua resposta deve refletir isso.
JimEvans
17
Veja que o único problema com isso é que quando você depura e mata a execução - o processo ainda permanece. Mesmo se você clicar em, Xele permanecerá. esse é o ÚNICO motivo para esse arquivo em lote. Obviamente quité o caminho a percorrer, no entanto, no meu exemplo, se você depurar e interromper a execução - nunca chegará ao quit.
ddavison
3
i estou respondendo a uma das perguntas: I hope there is a way I can write something to kill the chromedriver.exe process.. e sim, isso é bom! Java não faz isso
ddavison
3
Dependendo da estrutura de teste que você usa, você também pode acabar com processos fantasmas espalhados se os testes falharem em sua "configuração". NUnit, por exemplo, não chamará o método TestFixtureTearDown se algo no método TestFixtureSetup falhar -> você cria o navegador, faz alguma coisa e então executa o teste. Se algo der errado quando "você faz alguma coisa", é isso, o processo fica lá.
Arran
1
Se você usar a interface DriverService, mantenha o serviço até terminar de usar o driver e chame DriverService.stop () também. Para mim, o driver.quit () não era suficiente porque eu também estava usando DriverService.
Kimball Robinson
38

browser.close() irá fechar apenas a janela atual do Chrome.

browser.quit() deve fechar todas as janelas abertas e sair do webdriver.

Richard
fonte
9
Obrigado Richard. browser.quit()fechou todas as janelas abertas. Mas chromedriver.exe não foi encerrado. E havia uma mensagem de erro 'InvalidURL: porta não numérica:' porta ''.
KLI de
5
ESTÁ BEM. Eu tentei browser = webdriver.Firefox(). Ambos browser.close()e browser.quit()fecham todas as janelas e liberam memória. No entanto, o chromedriver não faria o mesmo.
KLI
Ei KLI. Aqui, onde trabalho, notamos exatamente as mesmas coisas acontecendo com o chromedriver. É por isso que temos um arquivo em lote que só executamos quando precisamos. chromedriver.exe não é um grande processo, mas apresenta um problema quando tentamos executar Project-> Clean por exemplo
ddavison
17

Teoricamente, chamar browser.Quit fechará todas as guias do navegador e encerrará o processo.

No entanto, no meu caso, não fui capaz de fazer isso - como estava executando vários testes em paralelo, não queria fazer um teste para fechar janelas para outros. Portanto, quando meus testes terminarem de ser executados, ainda haverá muitos processos "chromedriver.exe" em execução.

Para superar isso, escrevi um código de limpeza simples (C #):

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

foreach(var chromeDriverProcess in chromeDriverProcesses)
{
     chromeDriverProcess.Kill();
}
Illidan
fonte
Não ajudou. O processo não é
encerrado
@DenisKoreyba: Não acho que a linguagem de implementação deva mudar o comportamento. No sistema operacional Windows, quando o processo não está em poder de ninguém - você pode matá-lo (mesmo que ele segure, você pode forçar e matá-lo). Você está tentando eliminá-lo depois de fechar as guias do navegador?
Illidan
Estou usando C # para fazer isso, o que eu disse sobre java é que o processo do TeamCity é executado sob ele. Respondendo à sua pergunta: sim, primeiro eu invoco Dispose () e depois seu código.
Denis Koreyba
Isso não funciona no driver do Chrome, versão 2.21 pelo menos. O processo é eliminado, mas a janela do console ainda é exibida, provavelmente porque algum processo filho ainda persiste. A resposta de Alhanane abaixo funciona.
Silent Sojourner
Eu inseri o código de limpeza mencionado acima na seção AssemblyCleanup da BaseDriverClass. Como posso verificar se o processo chromedriver.exe foi realmente eliminado?
monkrus
12

Tive sucesso ao usar driver.close()antes driver.quit(). Antes eu estava apenas usando driver.quit().

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


driver.close();

driver.quit();
Shantonu
fonte
Isso não funcionou para mim. Chamando driver.close (); irá fechar o navegador e definir o driver como nulo. E então não há nenhum ponto de chamar driver.quit (); pois ele lançará uma exceção nula.
Priyanka
a implementação tem algumas mudanças no selênio atual, você pode não precisar quit () se o processo for encerrado. Certifique-se de que, ao fazer isso, o gerenciador de tarefas não tenha o processo do navegador interrompido.
Shantonu
7

É meio estranho, mas funciona para mim. Eu tive o problema semelhante, após algumas pesquisas, descobri que ainda havia uma ação de IU em andamento no navegador (carregamento de URL ou algo assim), quando eu bati WebDriver.Quit().

A solução para mim (embora muito desagradável) foi adicionar um Sleep()de 3 segundos antes de chamar Quit ().

Alpana Chauhan
fonte
3
Obrigado, isso realmente funcionou para mim também. Eu também estava usando WebDriver.Quit()antes, mas às vezes deixava um processo chrome.exe ativo. Além disso, acho que não está acontecendo em todos os sistemas operacionais.
Grengas
1
Isso funcionou para mim também! Pode fazer você se sentir um pouco sujo, mas às vezes aleatório. Thread.Sleeps parece ser o que o médico receitou para testes de IU.
Dan Csharpster
O mesmo para mim, fechar por conta própria ou sair por conta própria deixou o processo do driver para trás. Fazer as duas coisas bem limpas.
Mark Ball
Ótimo! Isso funcionou para mim também. Eu adicionei Task.Delay (TimeSpan.FromSeconds (3)); antes de chamar driver.Quit () e está fechando todos os arquivos chromedriver.exe
Priyanka
5

Esta resposta é como descartar corretamente o driver em C #

Se você quiser usar um mecanismo 'adequado' que deve ser usado para 'arrumar' após a execução, ChromeDriver você deve usar IWebDriver.Dispose();

Executa tarefas definidas pelo aplicativo associadas à liberação, liberação ou redefinição de recursos não gerenciados. (Herdado de IDisposable.)

Eu geralmente implemento IDisposablena aula que lida comIWebDriver

public class WebDriverController : IDisposable
{
    public IWebDriver Driver;

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

e usá-lo como:

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

Espero que isso te economize algum tempo

Matas Vaitkevicius
fonte
6
Posso confirmar que ainda existem problemas com esta estratégia! Estou usando Selenium WebDriver API .NET v3.13.1.0, minha instância do Chrome está atualizada e também meu Windows 10 ... Estou usando o ChromeDriver (que implementa IDisposable por herança) assim: using (var driver = new ChromeDriver()) { //my code here } Às vezes, nem sempre, "algo" (não sei o que ??) acontece e chromedriver.exeainda não foi lançado de acordo com meu gerenciador de tarefas.
Hauns TM
Sim, isso não corrige o bug para mim também.
Pxtl
4

Elimine vários processos da linha de comando A primeira coisa que você precisa fazer é abrir um prompt de comando e usar o comando taskkill com a seguinte sintaxe:

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

Esses parâmetros eliminarão à força qualquer processo que corresponda ao nome do executável que você especificar. Por exemplo, para matar todos os processos iexplore.exe, usaríamos:

taskkill /F /IM iexplore.exe

insira a descrição da imagem aqui

sumit kumar pradhan
fonte
3

Código 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;
            }
        }

    }

e esta função

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

Chamando

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

            }
Alhanane
fonte
Eu apliquei seu código como uma limpeza final. Até agora, parece funcionar. Bom trabalho!
Exzile
2

Eu tive o mesmo problema ao executá-lo em Python e tive que executar manualmente o comando 'killall' para encerrar todos os processos. No entanto, quando implementei o driver usando o protocolo de gerenciamento de contexto Python , todos os processos foram eliminados. Parece que o interpretador Python faz um ótimo trabalho de limpeza.

Aqui está a implementação:

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

E o uso:

with Browser() as browser:
    browser.navigate_to_page()
bruxo
fonte
2

Portanto, você pode usar o seguinte:

driver.close()

Feche o navegador (emula o toque no botão Fechar)

driver.quit()

Saia do navegador (emula a seleção da opção sair)

driver.dispose()

Saia do navegador (tenta fechar todas as guias e depois sai)

No entanto, se você AINDA está tendo problemas com instâncias suspensas (como eu), você também pode querer matar a instância. Para fazer isso, você precisa do PID da instância do 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)

Se sobrar uma instância do Chrome depois disso, comerei meu chapéu. :(

Rue Lazzaro
fonte
2

Código Python:

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

Eu sei que esta é uma questão antiga, mas pensei em compartilhar o que funcionou para mim. Eu estava tendo problemas com o Eclipse - ele não mataria os processos, então eu tinha um monte de processos fantasmas pendurados depois de testar o código usando o executor do Eclipse.

Minha solução foi executar o Eclipse como administrador. Isso resolveu para mim. Parece que o Windows não estava permitindo que o Eclipse fechasse o processo que ele gerou.

Forresthopkinsa
fonte
Isso faz muito sentido, mas no meu caso não funcionou, chromedriver.exepermanece visível entre os processos do Gerenciador de Tarefas, não importa se eu iniciei o Eclipse como administrador ou usuário normal. É possível que no meu caso seja esse o problema, porque chromedriver.exeé de 32 bits e meu JRE é de 64 bits. Eclipse Neon.1a (4.6.1), Windows 8.1 Pro 64 bits, Java 1.8.0_92-b14.
SantiBailors
1

Eu usei o seguinte em nightwatch.js em ganchos afterEach.

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

.closeWindow () simplesmente fecha a janela. (Mas não vai funcionar para várias janelas abertas). Enquanto .end () termina todos os processos de cromo restantes.

Simon Correia
fonte
0

Eu tenho esse problema. Eu suspeito que seja devido à versão do Serenity BDD e Selenium. O processo chromedriver nunca é liberado até que todo o conjunto de testes seja concluído. Existem apenas 97 testes, mas ter 97 processos consumindo a memória de um servidor que não tem muitos recursos pode estar afetando o desempenho.

Para resolver, fiz 2 coisas (isso é específico para o Windows).

  1. antes de cada teste (anotado com @Before) obtenha o ID do processo (PID) do processo chromedriver com:

    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. após cada teste (anotado com @After) elimine o PID com:

    Runtime.getRuntime().exec("taskkill /F /PID " + pid);
    
Dean McNabb
fonte
0

Eu vim aqui inicialmente pensando que isso teria sido respondido / resolvido, mas depois de ler todas as respostas, fiquei um pouco surpreso por ninguém tentar chamar todos os três métodos juntos:

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
}

Eu estava aqui apenas para procurar respostas e não tinha a intenção de fornecer uma. Portanto, a solução acima é baseada apenas na minha experiência. Eu estava usando o driver do Chrome em um aplicativo de console C # e consegui limpar os processos remanescentes somente depois de chamar todos os três métodos juntos.

Louie Bao
fonte
0

Para usuários do Ubuntu / Linux: - o comando é pkillou killall. pkillgeralmente é recomendado, pois em alguns sistemas, killallirá realmente matar todos os processos.

Manmohan_singh
fonte
0

Estou usando o Protractor com directConnect. Desativar a opção "--no-sandbox" corrigiu o problema para mim.

// 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
fonte
0
  • Certifique-se de obter a instância do Driver como Singleton
  • então aplique no final
  • driver.close ()
  • driver.quit ()

Nota: Agora, se virmos o gerenciador de tarefas, você não encontrará nenhum driver ou processo de cromo ainda travado

Sarath
fonte
0

Eu olhei todas as respostas e testei todas elas. Eu praticamente os compilei todos em um como um 'fechamento de segurança'. Isso em c #

NOTA você pode alterar o parâmetro do aplicativo IModule para o do driver real.

 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
fonte
0

Observado na versão 3.141.0:

Se você inicializar seu ChromeDriver apenas com ChromeOptions, quit () não fechará chromedriver.exe.

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

Se você criar e passar um ChromeDriverService, quit () fechará o chromedriver.exe corretamente.

    ChromeDriverService driverService = ChromeDriverService.CreateDefaultService();
    ChromeOptions chromeOptions = new ChromeOptions();
    ChromeDriver driver = new ChromeDriver(driverService, chromeOptions);
    // .. do stuff ..
    driver.quit()
vhoang
fonte
Esta é a solução em java que eu acredito. Pelo menos funcionou para mim
Isabelle T.
0

Eu simplesmente uso em cada teste um método tearDown () como a seguir e não tenho nenhum problema.

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

Depois de sair da instância do driver, limpe-a do cache por driver = null

Espero que a resposta a pergunta

Jamil
fonte
0

Existe outra maneira que está funcionando apenas para o Windows, mas agora está obsoleta. ele funciona para versões anteriores do selenium (funciona na versão 3.11.0).

import org.openqa.selenium.os.WindowsUtils;

 WindowsUtils.killByName("chromedriver.exe") // any process name you want
Norayr Sargsyan
fonte
0

Você deve aplicar antes de sair

driver.close()
driver.quit()
Sara Bouraya
fonte
Não funciona, chromedriver.exe ainda aberto
Pedro Joaquín
1
--Editar -> Removido "driver.close ()" e funcionou
Pedro Joaquín