Chromedriver не удаляет scoped* dir во временной папке после завершения теста
В последнем файле chromedriver.exe возникают проблемы с нехваткой места на диске, так как chromedriver не удаляет папку с именем scoped_* в конце выполнения. Он занимает почти 20 ГБ места для 400 тестов. Я попробовал с 2.28 и 2.29 версиями chromedriver. Я корректно завершаю работу драйвера с помощью driver.close() и driver.Quit(). Версия браузера Chrome - 57.
7 ответов
Мне удалось это, добавив удаление временных папок, которое начинается с "scoped_dir" после выхода из драйвера, например:
public static void teardown_()
{
// quit driver
if (driver != null)
driver.Quit();
// delete all "scoped_dir" temp folders
string tempfolder = System.IO.Path.GetTempPath();
string[] tempfiles = Directory.GetDirectories(tempfolder, "scoped_dir*", SearchOption.AllDirectories);
foreach (string tempfile in tempfiles)
{
try
{
System.IO.DirectoryInfo directory = new System.IO.DirectoryInfo(tempfolder);
foreach (System.IO.DirectoryInfo subDirectory in directory.GetDirectories()) subDirectory.Delete(true);
}
catch (Exception ex)
{
writeEx("File '" + tempfile + "' could not be deleted:\r\n" +
"Exception: " + ex.Message + ".");
}
}
}
Надеюсь, поможет!
Это известная ошибка, которая будет исправлена в Chromedriver 2.30 https://bugs.chromium.org/p/chromedriver/issues/detail?id=644
Похоже, что это состояние гонки между ChromeDriver и Chrome. ChromeDriver создает эти временные каталоги для использования Chrome, и в конце ChromeDriver пытается удалить эти каталоги. ChromeDriver ожидает завершения основного процесса Chrome, прежде чем выполнять удаление, но некоторые дочерние процессы Chrome могут все еще работать и удерживать эти каталоги, что приводит к сбою удаления. В настоящее время ChromeDriver не повторяет удаление.
Удаление временных файлов, как упомянул Дэниел, может быть временным решением, но я бы удалил его, как только выйдет Chromedriver 2.30.
Обновить
Chromedriver 2.30 вышел и должен решить эту проблему.
Используя последнюю версию chromedriver 2.30.1
не решил проблему для меня - у меня не хватало места в моем %TEMP%
каталог при выполнении параллельных заданий селена.
Лучшее решение - это контролировать userDataDir
через Chrome Options и распоряжайтесь каталогом самостоятельно после driver.quit()
Если ваш процесс является синхронным, то решение @ cdzar, описанное выше, будет работать, но для параллельных заданий вам действительно нужно контролировать каталог, создайте / утилизируйте его самостоятельно.
Вы можете проверить другие параметры командной строки Chromium здесь.
Было сообщено и исправлено. Оформить заказ 2.30 или 2.31
UPD. по крайней мере, работает для нашей сетки. Если у вас все еще есть проблемы, лучше сообщить о них в любой ветке scope_dir на productforums.google.com. Кроме того, до его исправления мы использовали скрипт PS, который очищал все файлы в.. * \ AppData \ Local \ Temp
UPD. проверьте, что браузер Chrome завершил процесс обновления. Наряду с этим исправлением у нас была проблема, заключающаяся в том, что браузер сохраняет состояние "требуется перезагрузка для завершения обновления" даже после перезагрузки. Может быть, и браузер и драйвер должны быть обновлены для исправления, чтобы работать - не могу сказать наверняка.
UPD2. Я вижу, что у некоторых людей все еще есть проблема. (может быть, они переиздали его?) Вот пример сценария PS, который использовался на машине Win в то время, когда у нас была проблема. Cleaner.ps1
#infinite loop for calling function
$ScriptPath = $MyInvocation.MyCommand.Definition
# 2030 year error
$timeout = new-timespan -end (get-date -year 2030 -month 1 -day 1)
$sw = [diagnostics.stopwatch]::StartNew()
while ($sw.elapsed -lt $timeout){
if (-Not (test-path $ScriptPath)){
write-host "v been renamed, quiting!"
return
}
start-sleep -seconds 60
# logic
$time=Get-Date
$maxdate = $time.AddMinutes(-120)
Get-WmiObject -Class Win32_UserProfile | Foreach-Object {
$path = $_.LocalPath
if (-Not $path.Contains('Windows')){
echo $path
$Files = Get-ChildItem "$($path)\..\*\AppData\Local\Temp" -recurse | ? {$_.LastWriteTime -lt $maxdate } |
remove-item -force -recurse
echo $Files
}
}
}
run.bat
#PowerShell -Command "Set-ExecutionPolicy Unrestricted" >> "%TEMP%\StartupLog.txt" 2>&1
PowerShell C:\path2CleanerFolder\Cleaner.ps1
GL
Это решение работает на Selenium 3.141.59. Прежде чем делать driver.quit()
в вашем методе разрыва, используйте driver.close()
, Selenium WebDriver автоматически удалит папки scoped_dir, которые он создает во время выполнения.
Мы запускаем несколько ChromeDriver с высокой степенью параллелизма, и я получил большое улучшение, используя идею Cornel об использовании добавления driver.close()
перед driver.quit()
в тесте. Может быть, это дает Chrome немного больше времени, чтобы завершить свои процессы перед выходом, предотвращая возникновение состояния гонки / блокировки?
Если окажется, что нам нужно сделать больше, я постараюсь кодировать ответ, аналогичный тому, который предоставил Дэниел, но из-за нашего уровня параллелизма я попытаюсь удалить определенные папки, созданные каждым экземпляром драйвера.
Название каталога можно получить следующим образом:
Capabilities caps = driver.getCapabilities();
Map<String, String> chromeReturnedCapsMap = (Map<String, String>) caps.getCapability("chrome");
LOG.debug(" Chrome Driver Temp Dir : " + chromeReturnedCapsMap.get("userDataDir"));
Это напечатает что-то вроде
Каталог драйверов Chrome: C:\Users\Metal666\AppData\Local\Temp\scoped_dir35344_14668
Однако создается впечатление, что созданы два каталога - они отличаются по имени после того, как будут подчеркнуты последними. Так, например, каталоги могут быть названы:
C: \ Users \ Metal666 \ AppData \ Local \ Temp \ scoped_dir35344_14668 C: \ Users \ Metal666 \ AppData \ Local \ Temp \ scoped_dir35344_28790
поэтому код должен был бы обслуживать удаление обоих файлов.
Протестировано с использованием Selenium 3.141.59, Chrome 74.0.., ChromeDriver 74.0..
Исправление как для синхронных, так и для параллельных хромированных драйверов , которое в настоящее время работает у меня, запускает 5 драйверов, Python (через pycharm или терминал):
Сначала объявите, добавьте собственный и уникальный идентификатор для каждого драйвера:
options.add_argument('--**foo**')
Также убедитесь, что вы указываете его на жесткий диск из-за перезаписи констант:
options.add_argument("--user-data-dir=**X:/path/to/dir**")
Использование psutil для отслеживания и уничтожения каждого драйвера на основе его уникального идентификатора, а затем Shutil для удаления папок:
def kill_driver():
while True:
running_processes = []
for proc in psutil.process_iter(['pid', 'cmdline']):
if proc.info['cmdline'] and **'--foo'** in proc.info['cmdline']:
running_processes.append(proc)
for process in running_processes:
process.kill()
print(process, ' got shot')
if not running_processes:
print('tudo fechado')
shutil.rmtree(**'X:/path/to/dir'**) # shutil to delete the folder
print('pasta excluida')
break
Я использую это в конце каждого выполнения и в исключениях:
if __name__ == '__main__':
while True:
try:
get_openings()
gc.collect()
print('marcano 10 - secundários')
kill_driver()
random_delay()
except Exception as e:
gc.collect()
logging.exception(f"An error occurred: {str(e)}")
print(f"An error occurred: {str(e)}")
kill_driver()
random_delay()
Желаем удачи и не забывайте об импорте!