Programing

메모리에서 Selenium chromedriver.exe 해제

lottogame 2020. 9. 5. 10:28
반응형

메모리에서 Selenium chromedriver.exe 해제


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


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을 실행할 때.


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

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


이론적으로 browser.Quit을 호출하면 모든 브라우저 탭이 닫히고 프로세스가 종료됩니다.

그러나 제 경우에는 그렇게 할 수 없었습니다. 여러 테스트를 병렬로 실행했기 때문에 하나의 테스트에서 다른 사람에게 창을 닫고 싶지 않았습니다. 따라서 테스트 실행이 완료되면 여전히 많은 "chromedriver.exe"프로세스가 실행되고 있습니다.

이를 극복하기 위해 간단한 정리 코드 (C #)를 작성했습니다.

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

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

driver.close()이전에 사용할 때 성공했습니다 driver.quit(). 이전에는 driver.quit().


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


driver.close();

driver.quit();

좀 이상하지만 나를 위해 작동합니다. 비슷한 문제가 있었는데, 약간의 파고를 한 후 .NET을 눌렀을 때 브라우저에서 여전히 UI 작업이 진행되고 있음을 발견했습니다 (URL 로딩 등) WebDriver.Quit().

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


이 답변은 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
}

이것이 시간을 절약하기를 바랍니다.


코드 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
            {

            }

파이썬에서 실행할 때도 같은 문제가 있었고 모든 프로세스를 죽이기 위해 '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()

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

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


afterEach 후크의 nightwatch.js에서 아래를 사용했습니다.

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

.closeWindow ()는 단순히 창을 닫습니다. (그러나 열린 여러 창에서는 작동하지 않습니다.) .end ()는 나머지 모든 크롬 프로세스를 종료합니다.


명령 줄에서 여러 프로세스 종료 가장 먼저해야 할 일은 명령 프롬프트를 열고 다음 구문으로 taskkill 명령을 사용하는 것입니다.

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

이러한 매개 변수는 지정한 실행 파일의 이름과 일치하는 모든 프로세스를 강제로 종료합니다. 예를 들어, 모든 iexplore.exe 프로세스를 종료하려면 다음을 사용합니다.

taskkill /F /IM iexplore.exe

여기에 이미지 설명 입력


따라서 다음을 사용할 수 있습니다.

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)

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


Python 코드 :

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

I have this issue. I suspect its due to the version of Serenity BDD and Selenium. The chromedriver process never releases until the entire test suite finishes. There are only 97 tests, but having 97 processes eat up the memory of a server that hasn't much resources may be having an affect on the performance.

To address I did 2 things (this is specific to windows).

  1. before each test (annotated with @Before) get the process id (PID) of the chromedriver process with:

    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 each test (annotated with @After) kill the PID with:

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

I came here initially thinking surely this would have been answered/resolved but after reading all the answers I was a bit surprised no one tried to call all three methods together:

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
}

I was only here to look for answers and didn't intend to provide one. So the above solution is based on my experience only. I was using chrome driver in a C# console app and I was able to clean up the lingering processes only after calling all three methods together.


For Ubuntu/Linux users: - the command is either pkill or killall . pkill is generally recommended, since on some systems, killall will actually kill all processes.


I am using Protractor with directConnect. Disabling the "--no-sandbox" option fixed the issue for me.

// 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"]
  }
},

  • Make Sure You get the Driver instance as Singleton
  • then Apply at end
  • driver.close()
  • driver.quit()

Note: Now if we see task manager you will not find any driver or chrome process still hanging


모든 응답을 살펴보고 모두 테스트했습니다. 나는 그것들을 모두 '안전 폐쇄'로 하나로 모았습니다. 이것은 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.
        }
    }

}

참고 URL : https://stackoverflow.com/questions/21320837/release-selenium-chromedriver-exe-from-memory

반응형