メモリからSelenium chromedriver.exeを解放する


102

Seleniumを実行するPythonコードをセットアップしましたchromedriver.exe。実行の最後browser.close()に、インスタンスを閉じる必要があります。(browser = webdriver.Chrome()chromedriver.exeメモリから解放されるはずです(Windows 7を使用しています)。ただし、実行するたびchromedriver.exeに、メモリにインスタンスが1 つ残っています。chromedriver.exeプロセスを強制終了するためにpythonで何かを書く方法があるといいのですが。明らかにbrowser.close()仕事をしません。ありがとう。


結論としては、デザイナーがプロセスを組み込まなかったため、何らかの方法でプロセスを強制終了する必要があります。他のすべての方法では、プロセスを実行したままにすることができますが、それだけで強制終了できます。
Stephen G

回答:


73

Selenium APIによるとbrowser.quit()、このメソッドはすべてのウィンドウを閉じてプロセスを終了するため、実際に呼び出す必要があります。引き続き使用する必要がありますbrowser.quit()

しかし:私の職場では、Javaプラットフォームでchromedriverテストを実行しようとしたときに大きな問題が発生しました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ても残ります。それはだONLYこのバッチファイルの理由。言うquitまでもありませんが、私の例では、デバッグして実行を停止した場合-に到達しませんquit
ddavison 2014年

3
私は質問の1つに答えていますI hope there is a way I can write something to kill the chromedriver.exe process.。はい、それはいいです!Javaはそれをしない
ddavison

3
使用するテストフレームワークによっては、テストが「セットアップ」で失敗した場合に、ファントムプロセスが横になってしまう可能性もあります。あなたは、ブラウザを作成し、いくつかのものを行う、と> - NUnitのは、例えば、TestFixtureSetup方法の失敗で何かあればTestFixtureTearDownメソッドの呼び出しをしませんその後、テストを実行します。「あなたが何かをする」ときに何かがうまくいかない場合、それだけです、プロセスはそこにとどまっています。
Arran

1
DriverServiceインターフェースを使用する場合は、ドライバーが完了するまでサービスを保持し、DriverService.stop()も呼び出します。私もDriverServiceを使用していたため、driver.quit()では不十分でした。
キンボールロビンソン

38

browser.close() 現在のクロムウィンドウのみを閉じます。

browser.quit() 開いているウィンドウをすべて閉じてから、webdriverを終了します。


9
リチャードに感謝します。browser.quit()開いているウィンドウをすべて閉じました。しかし、chromedriver.exeは終了しませんでした。また、エラーメッセージ 'InvalidURL:nonnumeric port:' port ''がありました。
KLI 2014年

5
OK。試しましたbrowser = webdriver.Firefox()。両方ともbrowser.close()browser.quit()すべてのウィンドウを閉じてメモリを解放します。ただし、chromedriverは同じことを行いません。
KLI 2014年

KLIさん、こんにちは。ここで私が作業しているところ、Chromedriverで同じことが起こっていることに気づきました。これが、必要なときにだけ実行するバッチファイルがある理由です。chromedriver.exeは大きなプロセスではありませんが、たとえばProject-> Cleanを実行しようとすると問題が発生します
ddavison

17

理論的には、browser.Quitを呼び出すと、すべてのブラウザタブが閉じ、プロセスが強制終了されます。

しかし、私の場合、それを行うことはできませんでした。複数のテストを並行して実行しているため、1つのテストで他のウィンドウを閉じる必要はありませんでした。したがって、テストの実行が終了しても、まだ多くの「chromedriver.exe」プロセスが実行中のままです。

それを克服するために、簡単なクリーンアップコード(C#)を書きました。

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

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

それは助けにはならなかった。プロセスがJavaで実行されている場合は
強制終了さ

@DenisKoreyba:実装の言語が行動を変えるべきだとは思いません。Windows OSでは、プロセスが誰にも保持されていない場合は、それを強制終了できます(保持されている場合でも、強制して強制終了できます)。ブラウザのタブが閉じた後にそれを強制終了しようとしていますか?
Illidan

私はこれを行うためにC#を使用しています。javaについて私が言ったことは、TeamCityのプロセスがその下で実行されるということです。あなたの質問への回答:はい、まずDispose()を呼び出してから、コードを呼び出します。
Denis Koreyba

これは、少なくともバージョン2.21のChromeドライバーでは機能しません。プロセスは強制終了されますが、おそらく一部の子プロセスがまだ残っているため、コンソールウィンドウは引き続き表示されます。以下のaalhananeの答えは機能します。
Silent Sojourner '19

上記のクリーンアップコードをBaseDriverClassのAssemblyCleanupセクションに挿入しました。chromedriver.exeプロセスが実際に強制終了されたことを確認するにはどうすればよいですか?
monkrus

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()を呼び出す意味はありません。null例外がスローされるため。
プリヤンカ

現在のセレンでは実装にいくつかの変更があり、プロセスが強制終了された場合はquit()は必要ない場合があります。これを行うときは、タスクマネージャーでブラウザープロセスが強制終了されないようにしてください。
Shantonu

7

それはちょっと奇妙ですが、私にとってはうまくいきます。同様の問題がありましたが、掘り下げた後、をクリックすると、ブラウザでUIアクション(URLの読み込みなど)がまだ行われていることがわかりましたWebDriver.Quit()

(非常に厄介ですが)私の解決策は、Sleep()Quit()を呼び出す前に3秒を追加することでした。


3
おかげで、これも実際に私のために働いた。WebDriver.Quit()以前も使用していましたが、ときどき1つのchrome.exeプロセスが生き残っていました。また、すべてのオペレーティングシステムで発生しているわけではないようです。
グレンガス

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
この戦略にはまだ問題があることを確認できます!私は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 2018

うん、これは私にとってもバグを修正しません。
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)

その後にクロムインスタンスが残っている場合は、帽子を食べます。:(



1

これは少し古い質問であることは承知していますが、自分にとって有効なことを共有したいと思いました。私はEclipseに問題を抱えていました-それはプロセスを殺すことはないので、Eclipseランナーを使用してコードをテストした後、たくさんのファントムプロセスがぶらぶらしていました。

私の解決策は、Eclipseを管理者として実行することでした。それで解決しました。WindowsはEclipseが生成したプロセスを閉じることをEclipseに許可していなかったようです。


これは非常に理にかなっていますが、私の場合は機能しませんでしたchromedriver.exe。Eclipseを管理者または通常のユーザーとして起動しても、タスクマネージャープロセスで表示されたままです。私の場合、32ビットで、JREが64ビットであるため、これが問題である可能性がありchromedriver.exeます。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個のプロセスがリソースの少ないサーバーのメモリを使い果たすと、パフォーマンスに影響を与える可能性があります。

対処するために2つのことを行いました(これは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をkillします:

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

0

私は最初に確かにこれが答えられた/解決されたであろうと思ってここに来ましたが、すべての答えを読んだ後、3つすべてのメソッドを一緒に呼び出そうとする人がいないことに少し驚きました:

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ドライバーを使用していて、3つのメソッドすべてを同時に呼び出した後にのみ、残留プロセスをクリーンアップできました。


0

Ubuntu / Linuxユーザーの場合:-コマンドはまたはのいずれpkillkillallです。pkill一部のシステムでkillallは、実際にはすべてのプロセスが強制終了されるため、一般的に推奨されます。


0

Protractorと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.close()
  • driver.quit()

注:タスクマネージャーが表示されている場合は、ドライバーやChromeプロセスがまだハングしていません。


0

私はすべての応答を見て、それらすべてをテストしました。私はそれらをすべて「安全クロージャ」として1つにまとめました。これは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

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.