libérer Selenium chromedriver.exe de la mémoire


102

J'ai mis en place un code python pour exécuter Selenium chromedriver.exe. À la fin de l'exécution, je dois browser.close()fermer l'instance. ( browser = webdriver.Chrome()) Je pense qu'il devrait sortir chromedriver.exede la mémoire (je suis sous Windows 7). Cependant, après chaque exécution, il reste une chromedriver.exeinstance dans la mémoire. J'espère qu'il existe un moyen d'écrire quelque chose en python pour tuer le chromedriver.exeprocessus. Il browser.close()ne fait évidemment pas le travail. Merci.


En bout de ligne ... vous devez tuer le processus d'une manière ou d'une autre parce que les concepteurs ne l'ont pas intégré. Toutes les autres méthodes peuvent laisser un processus en cours d'exécution et cela suffit pour justifier la suppression.
Stephen G

Réponses:


73

par l'API Selenium, vous devriez vraiment appeler browser.quit()car cette méthode fermera toutes les fenêtres et tue le processus. Vous devriez toujours utiliser browser.quit().

Cependant : sur mon lieu de travail, nous avons remarqué un énorme problème en essayant d'exécuter des tests chromedriver sur la plate-forme Java, où le chromedriver.exe existe encore même après utilisation browser.quit(). Pour contrer cela, nous avons créé un fichier batch similaire à celui ci-dessous, qui force simplement la fermeture des processus.

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

Puisque chromedriver.exe n'est pas un programme volumineux et ne consomme pas beaucoup de mémoire, vous ne devriez pas avoir à l'exécuter à chaque fois, mais uniquement lorsque cela pose un problème. Par exemple, lors de l'exécution de Project-> Clean dans Eclipse.


3
Je ne peux tolérer aucune réponse qui recommande de tuer des processus sans mentionner également la bonne façon de terminer ces processus normalement. Si vous utilisez correctement la quitméthode, cela ne devrait pas être un problème. La suppression forcée des processus ne devrait être qu’un dernier recours, et votre réponse devrait refléter cela.
JimEvans

17
Voyez le seul problème avec ceci, c'est que lorsque vous déboguez et tuez l'exécution - le processus reste toujours. Même si vous cliquez sur, Xil reste. c'est la SEULE raison de ce fichier de commandes. C'est évidemment quitla voie à suivre, mais dans mon exemple, si vous déboguez et arrêtez l'exécution - il n'atteint jamais le quit.
ddavison

3
Je réponds à l' une des questions suivantes : I hope there is a way I can write something to kill the chromedriver.exe process.. et oui, c'est sympa! Java ne fait pas ça
ddavison

3
Selon le framework de test que vous utilisez, vous pouvez également vous retrouver avec des processus fantômes traîner si les tests échouent dans sa "configuration". NUnit, par exemple, n'appellera pas la méthode TestFixtureTearDown si quelque chose dans la méthode TestFixtureSetup échoue -> vous créez le navigateur, faites des choses, puis exécutez le test. Si quelque chose ne va pas quand "vous faites des choses", c'est tout, le processus reste là.
Arran

1
Si vous utilisez l'interface DriverService, maintenez le service jusqu'à ce que vous en ayez terminé avec le pilote, et appelez également DriverService.stop (). Pour moi, le driver.quit () n'était pas suffisant car j'utilisais aussi DriverService.
Kimball Robinson

38

browser.close() fermera uniquement la fenêtre Chrome actuelle.

browser.quit() devrait fermer toutes les fenêtres ouvertes, puis quitter Webdriver.


9
Merci Richard. browser.quit()a fermé toutes les fenêtres ouvertes. Mais chromedriver.exe n'a pas été quitté. Et il y avait un message d'erreur 'InvalidURL: port non numérique:' port ''.
KLI

5
D'ACCORD. J'ai essayé browser = webdriver.Firefox(). Les deux browser.close()et browser.quit()fermerait toutes les fenêtres et la mémoire de sortie. Cependant, chromedriver ne ferait pas la même chose.
KLI

Salut KLI. Ici où je travaille, nous avons remarqué exactement les mêmes choses qui se produisent avec chromedriver. C'est pourquoi nous avons un fichier batch que nous n'exécutons que lorsque nous en avons besoin. chromedriver.exe n'est pas un gros processus, mais il présente un problème lorsque nous essayons d'exécuter Project-> Clean par exemple
ddavison

17

Théoriquement, appeler browser.Quit fermera tous les onglets du navigateur et tuera le processus.

Cependant, dans mon cas, je n'ai pas pu le faire - puisque j'exécute plusieurs tests en parallèle, je ne voulais pas qu'un test ferme les fenêtres à d'autres. Par conséquent, lorsque mes tests se terminent, il reste encore de nombreux processus "chromedriver.exe" en cours d'exécution.

Afin de surmonter cela, j'ai écrit un code de nettoyage simple (C #):

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

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

Cela n'a pas aidé. Le processus n'est pas tué lorsqu'il est exécuté sous java
Denis Koreyba

@DenisKoreyba: Je ne pense pas que le langage de mise en œuvre devrait changer les comportements. Sur le système d'exploitation Windows, lorsque le processus n'est détenu par personne - vous pouvez le tuer (même s'il a tenu, vous pouvez le forcer et le tuer). Essayez-vous de le tuer après la fermeture des onglets du navigateur?
Illidan

J'utilise C # pour ce faire, ce que j'ai dit à propos de java, c'est que le processus de TeamCity est exécuté sous celui-ci. Réponse à votre question: oui, j'invoque d'abord Dispose () puis votre code.
Denis Koreyba

Cela ne fonctionne pas sur le pilote chrome, au moins la version 2.21. Le processus est arrêté mais la fenêtre de la console s'affiche toujours, probablement parce qu'un processus enfant persiste. La réponse d'aalhanane ci-dessous fonctionne.
Silent Sojourner

J'ai inséré le code de nettoyage susmentionné dans la section AssemblyCleanup de BaseDriverClass. Comment puis-je vérifier que le processus chromedriver.exe a bien été tué?
monkrus

12

J'ai eu du succès lors de l'utilisation driver.close()avant driver.quit(). J'utilisais auparavant uniquement driver.quit().


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


driver.close();

driver.quit();

Cela n'a pas fonctionné pour moi. Appel de driver.close (); fermera le navigateur et définira le pilote sur null. Et puis il est inutile d'appeler driver.quit (); car il lèvera une exception nulle.
Priyanka

l'implémentation a quelques changements dans le sélénium actuel, vous n'aurez peut-être pas besoin de quit () si le processus est tué. Assurez-vous que lorsque vous faites cela, votre gestionnaire de tâches ne devrait pas avoir tué le processus du navigateur.
Shantonu le

7

C'est un peu étrange mais ça marche pour moi. J'ai eu le même problème, après quelques recherches, j'ai trouvé qu'il y avait encore une action d'interface utilisateur en cours dans le navigateur (chargement d'URL ou plus), lorsque j'ai frappé WebDriver.Quit().

La solution pour moi (bien que très désagréable) était d'ajouter Sleep()3 secondes avant d'appeler Quit ().


3
Merci, cela a fonctionné pour moi aussi. J'utilisais WebDriver.Quit()aussi avant, mais parfois il laissait un processus chrome.exe en vie. De plus, je suppose que cela ne se produit pas sur tous les systèmes d'exploitation.
Grengas

1
Cela a fonctionné pour moi aussi! Cela peut vous faire vous sentir un peu sale, mais parfois aléatoire. Le sommeil semble être ce que le médecin a prescrit pour les tests d'interface utilisateur.
Dan Csharpster

Pareil pour moi, fermer tout seul ou quitter de son propre chef a laissé le processus pilote derrière. Faire les deux bien nettoyé.
Mark Ball

Génial! Cela a fonctionné pour moi aussi. J'ai ajouté Task.Delay (TimeSpan.FromSeconds (3)); avant d'appeler driver.Quit () et il ferme tous les fichiers chromedriver.exe
Priyanka

5

Cette réponse est de savoir comment supprimer correctement le pilote en C #

Si vous souhaitez utiliser un mécanisme `` approprié '' qui devrait être utilisé pour `` ranger '' après l'exécution, ChromeDriver vous devez utiliser IWebDriver.Dispose();

Exécute les tâches définies par l'application associées à la libération, à la libération ou à la réinitialisation des ressources non gérées. (Hérité de IDisposable.)

J'implémente généralement IDisposablesur la classe qui traiteIWebDriver

public class WebDriverController : IDisposable
{
    public IWebDriver Driver;

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

et utilisez-le comme:

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

J'espère que cela vous fera gagner du temps


6
Je peux confirmer qu'il y a encore des problèmes avec cette stratégie! J'utilise Selenium WebDriver API .NET v3.13.1.0, mon instance Chrome est à jour, tout comme mon Windows 10 ... J'utilise ChromeDriver (qui implémente IDisposable par héritage) comme ceci: using (var driver = new ChromeDriver()) { //my code here } Parfois, pas toujours, "quelque chose" (je ne sais pas quoi ??) se produit et chromedriver.exen'est toujours pas publié selon mon gestionnaire de tâches.
Hauns TM

Oui, cela ne résout pas le bogue pour moi non plus.
Pxtl

4

Tuer plusieurs processus à partir de la ligne de commande La première chose à faire est d'ouvrir une invite de commande, puis d'utiliser la commande taskkill avec la syntaxe suivante:

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

Ces paramètres tueront de force tout processus correspondant au nom de l'exécutable que vous spécifiez. Par exemple, pour tuer tous les processus iexplore.exe, nous utiliserions:

taskkill /F /IM iexplore.exe

entrez la description de l'image ici


3

Code c #

en utilisant System.Diagnostics;

en utilisant 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;
            }
        }

    }

et cette fonction

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

Appel

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

            }

J'ai appliqué votre code en guise de nettoyage final. Jusqu'à présent, cela semble fonctionner. Bon travail!
Exzile

2

J'ai eu le même problème lors de son exécution en Python et j'ai dû exécuter manuellement la commande «killall» pour tuer tous les processus. Cependant, lorsque j'ai implémenté le pilote à l'aide du protocole de gestion de contexte Python , tous les processus avaient disparu. Il semble que l'interpréteur Python fasse un très bon travail de nettoyage.

Voici la mise en œuvre:

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

Et l'utilisation:

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

2

Ainsi, vous pouvez utiliser ce qui suit:

driver.close()

Fermez le navigateur (émule le fait d'appuyer sur le bouton de fermeture)

driver.quit()

Quittez le navigateur (émule la sélection de l'option Quitter)

driver.dispose()

Quittez le navigateur (essaie de fermer chaque onglet, puis quittez)

Cependant, si vous rencontrez TOUJOURS des problèmes avec des instances suspendues (comme je l'étais), vous voudrez peut-être également tuer l'instance. Pour ce faire, vous avez besoin du PID de l'instance 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)

S'il reste une instance de chrome après cela, je mangerai mon chapeau. :(


2

Code Python:

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

1

Je sais que c'est un peu une vieille question, mais j'ai pensé partager ce qui a fonctionné pour moi. J'avais des problèmes avec Eclipse - cela ne tuerait pas les processus, et j'ai donc eu un tas de processus fantômes qui traînaient après avoir testé le code à l'aide du runner Eclipse.

Ma solution était d'exécuter Eclipse en tant qu'administrateur. Cela m'a arrangé. Il semble que Windows n'autorisait pas Eclipse à fermer le processus qu'il a engendré.


Cela a beaucoup de sens, mais dans mon cas, cela n'a pas fonctionné, chromedriver.exereste visible parmi les processus du gestionnaire de tâches, peu importe que je lance Eclipse en tant qu'administrateur ou utilisateur normal. Il est possible que dans mon cas, ce soit le problème, car chromedriver.exec'est 32 bits et mon JRE est 64 bits. Eclipse Neon.1a (4.6.1), Windows 8.1 Pro 64 bits, Java 1.8.0_92-b14.
SantiBailors

1

J'ai utilisé ce qui suit dans nightwatch.js dans afterEach hooks.

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

.closeWindow () ferme simplement la fenêtre. (Mais ne fonctionnera pas pour plusieurs fenêtres ouvertes). Alors que .end () met fin à tous les processus de chrome restants.


0

J'ai ce problème. Je soupçonne que c'est dû à la version de Serenity BDD et Selenium. Le processus chromedriver ne se libère jamais tant que la suite de tests n'est pas terminée. Il n'y a que 97 tests, mais 97 processus consomment la mémoire d'un serveur qui n'a pas beaucoup de ressources peut avoir un impact sur les performances.

Pour aborder j'ai fait 2 choses (ceci est spécifique à Windows).

  1. avant chaque test (annoté avec @Before), obtenez l'identifiant du processus (PID) du processus chromedriver avec:

    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. après chaque test (annoté avec @After), tuez le PID avec:

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

0

Je suis venu ici au départ en pensant que cela aurait sûrement été répondu / résolu, mais après avoir lu toutes les réponses, j'ai été un peu surpris que personne n'ait essayé d'appeler les trois méthodes ensemble:

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
}

Je n'étais ici que pour chercher des réponses et je n'avais pas l'intention d'en fournir une. La solution ci-dessus est donc basée uniquement sur mon expérience. J'utilisais le pilote chrome dans une application console C # et j'ai pu nettoyer les processus persistants uniquement après avoir appelé les trois méthodes ensemble.


0

Pour les utilisateurs d'Ubuntu / Linux: - la commande est soit pkillou killall. pkillest généralement recommandé, car sur certains systèmes, il killallva en fait tuer tous les processus.


0

J'utilise Protractor avec directConnect. La désactivation de l'option "--no-sandbox" a résolu le problème pour moi.

// 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
  • Assurez-vous d'obtenir l'instance de pilote en tant que Singleton
  • puis Appliquer à la fin
  • driver.close ()
  • driver.quit ()

Remarque: maintenant, si nous voyons le gestionnaire de tâches, vous ne trouverez aucun pilote ou processus chrome toujours suspendu


0

J'ai regardé toutes les réponses et les ai toutes testées. Je les ai presque tous rassemblés en un seul sous forme de «fermeture de sécurité». Ceci en c #

REMARQUE vous pouvez changer le paramètre de l'application IModule à celui du pilote réel.

 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

Observé sur la version 3.141.0:

Si vous initialisez votre ChromeDriver avec seulement ChromeOptions, quit () ne fermera pas chromedriver.exe.

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

Si vous créez et transmettez un ChromeDriverService, quit () fermera correctement chromedriver.exe.

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

C'est la solution en java je crois. Au moins, ça a marché pour moi
Isabelle T.

0

J'utilise simplement dans chaque test une méthode tearDown () comme suit et je n'ai aucun problème.

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

Après avoir quitté l'instance de pilote, effacez-la du cache par driver = null

J'espère que la réponse à la question


0

Il existe une autre méthode qui ne fonctionne que pour Windows, mais elle est désormais obsolète. cela fonctionne pour les versions précédentes de sélénium (cela fonctionne sur la version 3.11.0).

import org.openqa.selenium.os.WindowsUtils;

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

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.