메모리에서 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.