메모리에서 Selenium chromedriver.exe 해제


102

Selenium을 실행하기 위해 파이썬 코드를 설정했습니다 chromedriver.exe. 실행이 끝나면 browser.close()인스턴스를 닫아야합니다. ( browser = webdriver.Chrome()) chromedriver.exe메모리에서 해제되어야한다고 생각합니다 (Windows 7에 있습니다). 그러나 각 실행 후에는 하나의 chromedriver.exe인스턴스가 메모리에 남아 있습니다. chromedriver.exe프로세스 를 죽이기 위해 파이썬으로 무언가를 작성할 수있는 방법이 있기를 바랍니다 . 분명히 일을 browser.close()하지 않습니다. 감사.


결론은 ... 디자이너가 프로세스를 구축하지 않았기 때문에 어떻게 든 프로세스를 종료해야합니다. 다른 모든 방법은 프로세스를 실행 상태로 둘 수 있으며 이는 종료를 보증하기에 충분합니다.
Stephen G

답변:


73

Selenium API에 따라이 browser.quit()메서드는 모든 창을 닫고 프로세스를 종료하므로 실제로 호출해야 합니다. 여전히 browser.quit().

그러나 : 제 직장에서 우리는 자바 플랫폼에서 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.있습니다. 그리고 네, 좋습니다! 자바는 그렇게하지 않습니다
ddavison 2014 년

3
사용하는 테스트 프레임 워크에 따라 테스트가 "설정"에서 실패하면 가상 프로세스가 주변에 놓일 수도 있습니다. 예를 들어 NUnit은 TestFixtureSetup 메서드의 무언가가 실패하면 TestFixtureTearDown 메서드를 호출하지 않습니다.-> 브라우저를 만들고 몇 가지 작업 수행 한 다음 테스트 실행합니다. "당신이 어떤 일을 할 때"뭔가 잘못되면, 그 과정은 거기에 머무르는 것입니다.
Arran 2014 년

1
DriverService 인터페이스를 사용하는 경우 드라이버 작업이 완료 될 때까지 서비스를 유지하고 DriverService.stop ()도 호출합니다. 나를 위해 DriverService를 사용했기 때문에 driver.quit ()만으로는 충분하지 않았습니다.
Kimball Robinson

38

browser.close() 현재 크롬 창만 닫습니다.

browser.quit() 열려있는 모든 창을 닫은 다음 webdriver를 종료해야합니다.


9
고마워 리차드. browser.quit()열려있는 모든 창을 닫았습니다. 그러나 chromedriver.exe는 종료되지 않았습니다. 그리고 'InvalidURL : 숫자가 아닌 포트 :'port '라는 오류 메시지가 표시되었습니다.
KLI

5
확인. 나는 시도했다 browser = webdriver.Firefox(). browser.close()및 둘 다 browser.quit()모든 창을 닫고 메모리를 해제합니다. 그러나 chromedriver는 동일한 작업을 수행하지 않습니다.
KLI

안녕 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();
}

도움이되지 않았습니다. 이 자바에서 실행할 때 프로세스는 살해되지 않는다
데니스 Koreyba을

@DenisKoreyba : 구현 언어가 행동을 바꿔야한다고 생각하지 않습니다. Windows OS에서 프로세스가 아무도 보유하지 않은 경우 프로세스를 종료 할 수 있습니다 (보유하더라도 강제로 종료 할 수 있음). 브라우저 탭을 닫은 후 종료하려고합니까?
Illidan

이 작업을 수행하기 위해 C #을 사용하고 있으며 Java에 대해 말한 것은 TeamCity의 프로세스가 그 아래에서 실행된다는 것입니다. 귀하의 질문에 대답 : 예, 먼저 Dispose ()를 호출 한 다음 코드를 호출합니다.
Denis Koreyba

크롬 드라이버, 버전 2.21 이상에서는 작동하지 않습니다. 프로세스가 종료되었지만 일부 하위 프로세스가 계속 유지되기 때문에 콘솔 창이 계속 표시됩니다. 아래 aalhanane의 답변이 작동합니다.
Silent Sojourner

위에서 언급 한 정리 코드를 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 예외가 발생하므로
Priyanka

구현에 현재 셀레늄이 약간 변경되었으므로 프로세스가 종료되면 quit ()가 필요하지 않을 수 있습니다. 그렇게 할 때 작업 관리자가 브라우저 프로세스를 종료하지 않아야합니다.
Shantonu

7

좀 이상하지만 나를 위해 작동합니다. 비슷한 문제가 있었는데, 몇 가지 파고 들었을 때 WebDriver.Quit().

나를위한 해결책은 (매우 불쾌하지만) Sleep()Quit ()를 호출하기 전에 3 초 를 추가하는 것이 었습니다 .


3
감사합니다. 이것은 실제로 저에게도 효과적이었습니다. 나는 WebDriver.Quit()이전에도 사용 했지만 때로는 하나의 chrome.exe 프로세스가 살아 남았습니다. 또한 모든 운영 체제에서 발생하는 것은 아닙니다.
Grengas

1
이것은 나에게도 효과적이었습니다! 그것은 당신이 약간 더럽다고 느낄 수 있지만 때로는 무작위 Thread.Sleeps는 의사가 UI 테스트를 위해 주문한 것 같습니다.
Dan Csharpster

나에게도 똑같이, 스스로 닫거나 스스로 종료하면 드라이버 프로세스가 뒤쳐졌습니다. 둘 다 잘 정리했습니다.
Mark Ball

큰! 이것은 나에게도 효과적이었습니다. 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

네, 이것은 나에게도 버그를 수정하지 않습니다.
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

파이썬에서 실행할 때도 같은 문제가 있었고 모든 프로세스를 죽이기 위해 'killall'명령을 수동으로 실행해야했습니다. 그러나 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()

브라우저 종료 (모든 탭을 닫으려고 시도한 다음 종료)

그러나 인스턴스 중단 문제 가 여전히 발생하는 경우 인스턴스를 종료 할 수도 있습니다. 이를 위해서는 크롬 인스턴스의 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)

그 후 남은 크롬 인스턴스가 있으면 모자를 먹을 게요. :(


2

Python 코드 :

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

1

나는 이것이 다소 오래된 질문이라는 것을 알고 있지만 나는 나를 위해 일한 것을 공유 할 것이라고 생각했습니다. 나는 이클립스에 문제가 있었다. 프로세스를 죽이지 않을 것이기 때문에 이클립스 러너를 사용하여 코드를 테스트 한 후에 많은 팬텀 프로세스가 있었다.

내 솔루션은 Eclipse를 관리자로 실행하는 것이 었습니다. 그것은 나를 위해 그것을 고쳤습니다. Windows가 Eclipse가 생성 한 프로세스를 닫는 것을 허용하지 않은 것 같습니다.


이것은 많은 의미가 있지만 제 경우에는 작동하지 않았으며 chromedriver.exeEclipse를 관리자 또는 일반 사용자로 시작하더라도 작업 관리자 프로세스 사이에 계속 표시됩니다. 제 경우에는 32 비트이고 JRE가 64 비트 이기 때문에 이것이 문제 일 가능성 chromedriver.exe 있습니다. Eclipse Neon.1a (4.6.1), Windows 8.1 Pro 64 비트, Java 1.8.0_92-b14.
SantiBailors

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 ()는 나머지 모든 크롬 프로세스를 종료합니다.


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 # 콘솔 앱에서 크롬 드라이버를 사용하고 있었고 세 가지 메서드를 모두 호출 한 후에 만 ​​느린 프로세스를 정리할 수있었습니다.


0

Ubuntu / Linux 사용자의 경우 :-명령은 pkill또는 killall. pkill일부 시스템에서는 killall실제로 모든 프로세스를 종료 하므로 일반적으로 권장 됩니다.


0

DirectConnect와 함께 Protractor를 사용하고 있습니다. "--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 ()

참고 : 이제 작업 관리자가 표시되면 여전히 중단 된 드라이버 또는 크롬 프로세스를 찾을 수 없습니다.


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

이것은 내가 믿는 자바의 솔루션입니다. 적어도 그것은 나를 위해 일했습니다
Isabelle T.

0

모든 테스트에서 다음과 같이 tearDown () 메서드를 사용하기 만하면 전혀 문제가 없습니다.

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

드라이버 인스턴스를 종료 한 후 드라이버 = null로 캐시에서 삭제

질문에 대한 답변을 바랍니다


0

창에서만 작동하는 또 다른 방법이 있지만 지금은 더 이상 사용되지 않습니다. 이전 셀레늄 릴리스에서 작동합니다 (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.