"No such file or directory" firefox selenium 测试完成后的错误信息
"No such file or directory" error message upon completion of firefox selenium test
我在使用 geckodriver (firefox) 运行 宁我的 python selenium 测试后出现一条标准输出错误消息,但在使用 chrome 时不会出现。 我不知道错误行是从哪里来的。它发生在调用 sys.exit() 之后,所以在清理过程中的某个地方。
[Errno 2] No such file or directory: '/var/folders/ml/tbnznl592397p4h1svx4t5xr0000gr/T/tmpr8ypd0y1'
- MacOS 10.14.5(莫哈韦沙漠)
- 驱动信息:firefox=67.0
- 会话信息:firefox=0.24.0
- 硒 3.141.0
- Python 3.7.3
这是 firefox 和 chrome 的驱动程序初始化。
def createDriver(self, browser: str, headless: bool = False, performancelog=False,
consolelog=False, verbose: bool = False):
## DRIVERS
#chrome
# https://chromedriver.storage.googleapis.com/index.html
#firefox
# https://github.com/mozilla/geckodriver/releases
# 20.1 has a bug where headless doesn't work
# 19 has a bug where it closes a frame?
# safari
# edge
# https://developer.microsoft.com/en-us/microsoft-edge/tools/webdriver/
logger.trace("createDriver()")
if browser.upper() == 'FIREFOX':
## setting log_path to /dev/null will prevent geckodriver from creating it's own log file.
## if we enable root logging, we can capture the logging from geckodriver, ourselves.
options = webdriver.FirefoxOptions()
profile = webdriver.FirefoxProfile()
profile.set_preference('app.update.auto', False)
profile.set_preference('app.update.enabled', False)
# options.binary_location = binary ## use this only if we want to move the executable outside the available path
if headless:
options.headless = True
caps = DesiredCapabilities.FIREFOX
caps['unhandledPromptBehavior'] = "ignore"
driver = webdriver.Firefox(profile, log_path='/dev/null', firefox_options=options,
desired_capabilities=caps
)
logger.debug(f"Driver info: firefox={driver.capabilities['browserVersion']}")
logger.debug(f"Session info: firefox={driver.capabilities['moz:geckodriverVersion']}")
if driver.capabilities['moz:geckodriverVersion'] == '0.20.1':
if headless:
raise Exception("Headless mode doesn't work in Gecko Driver 0.20.1")
elif browser.upper() == 'CHROME':
options = webdriver.ChromeOptions()
options.add_argument("--disable-extensions")
options.add_argument("--allow-running-insecure-content")
options.add_argument("--ignore-certificate-errors")
options.add_argument("--disable-single-click-autofill")
options.add_argument("--disable-autofill-keyboard-accessory-view[8]")
options.add_argument("--disable-full-form-autofill-ios")
options.add_argument("--dns-prefetch-disable") # https://bugs.chromium.org/p/chromedriver/issues/detail?id=402#c128
## ChromeDriver is just AWFUL because every version or two it breaks unless you pass cryptic arguments
options.add_argument("start-maximized") #
options.add_argument("enable-automation") #
options.add_argument("--no-sandbox") #
options.add_argument("--disable-infobars") #
options.add_argument("--disable-dev-shm-usage") #
options.add_argument("--disable-browser-side-navigation") #
options.add_argument("--disable-gpu") #
# options.add_argument("--window-size=1280,960")
options.add_argument("--enable-features=NetworkService,NetworkServiceInProcess") # https://groups.google.com/forum/m/#!topic/chromedriver-users/ktp-s_0M5NM[21-40]
if headless:
options.headless = True
# options.add_argument('--disable-gpu')
args = [
"--verbose"
]
caps = DesiredCapabilities.CHROME
caps['loggingPrefs'] = {
'browser': 'OFF',
'performance' : 'OFF',
'driver' : 'OFF'
}
# https://www.skptricks.com/2018/08/timed-out-receiving-message-from-renderer-selenium.html
# caps['pageLoadStrategy'] = 'none'
# caps['pageLoadStrategy'] = 'normal'
if consolelog:
caps['loggingPrefs']['browser'] = 'ALL'
## by default performance is disabled.
if performancelog:
caps['loggingPrefs']['performance'] = 'ALL'
caps['perfLoggingPrefs'] = {
'enableNetwork' : True,
'enablePage' : False,
'enableTimeline' : False
}
if verbose:
driver = webdriver.Chrome(options=options, service_log_path='chromedriver.log', service_args=args,
desired_capabilities=caps
)
else:
driver = webdriver.Chrome(options=options,
# service_log_path='chromedriver.log',
desired_capabilities=caps
)
logger.debug(f"Driver info: chrome={driver.capabilities['chrome']['chromedriverVersion']}")
logger.debug(f"Session info: chromedriver={driver.capabilities['version']}")
elif browser.upper() == 'EDGE':
# driver = webdriver.Edge()
raise NotImplemented("Edge not supported yet")
elif browser.upper() == 'SAFARI':
# driver = webdriver.Safari()
raise NotImplemented("Safari not supported yet")
# support is depricated for this -- should use chrome or firefox headless.
elif browser.upper() == 'PHANTOMJS':
# driver = webdriver.PhantomJS()
raise NotImplemented("PhantomJS not supported yet")
else:
raise ValueError(f"Unknown browser: {browser}")
# driver.set_page_load_timeout(self.timeout)
# driver.set_script_timeout(self.timeout)
return driver
在这两种情况下,驱动程序都位于处理自动退出驱动程序的包装器中。
############################################################################
def close(self):
if self.driver is not None:
self.driver.close()
############################################################################
def quit(self):
if self.driver is not None:
self.driver.quit()
############################################################################
def __del__(self):
self.quit()
在退出脚本之前调用 close 或 quit 不会触发让我感到困惑的错误消息。我原以为错误消息是垃圾收集时 geckodriver 中的某些内容,但如果是这种情况,我认为我可以通过在 sys.exit().
之前关闭驱动程序来手动触发错误
任何人都知道在 firefox selenium 运行 之后此错误消息的来源?
编辑:
看起来有问题的文件夹是 FirefoxProfile
创建的临时目录。我认为 firefox.WebDriver.quit()
方法是日志行的来源。
def quit(self):
"""Quits the driver and close every associated window."""
try:
RemoteWebDriver.quit(self)
except Exception:
# We don't care about the message because something probably has gone wrong
pass
if self.w3c:
self.service.stop()
else:
self.binary.kill()
if self.profile is not None:
try:
shutil.rmtree(self.profile.path)
if self.profile.tempfolder is not None:
shutil.rmtree(self.profile.tempfolder)
except Exception as e:
print(str(e)) #<-- this is the line where the error occurs.
啊!我完全忘记了我向 Firefox webdriver 添加了一个 __del__
方法。 (这是在我编写包装器之前)
# hack to force firefox to quit when closing scope
def __del_replacement__(self: webdriver.Firefox):
print("__del__ called in Firefox")
self.quit()
webdriver.Firefox.__del__ = __del_replacement__
问题是 webdriver 的包装器中还有一个 __del__
方法,它也试图调用 driver.quit()
。问题是由两次调用 quit()
方法试图删除临时目录引起的。第二个失败了,因为它已经被删除了。
我在使用 geckodriver (firefox) 运行 宁我的 python selenium 测试后出现一条标准输出错误消息,但在使用 chrome 时不会出现。 我不知道错误行是从哪里来的。它发生在调用 sys.exit() 之后,所以在清理过程中的某个地方。
[Errno 2] No such file or directory: '/var/folders/ml/tbnznl592397p4h1svx4t5xr0000gr/T/tmpr8ypd0y1'
- MacOS 10.14.5(莫哈韦沙漠)
- 驱动信息:firefox=67.0
- 会话信息:firefox=0.24.0
- 硒 3.141.0
- Python 3.7.3
这是 firefox 和 chrome 的驱动程序初始化。
def createDriver(self, browser: str, headless: bool = False, performancelog=False,
consolelog=False, verbose: bool = False):
## DRIVERS
#chrome
# https://chromedriver.storage.googleapis.com/index.html
#firefox
# https://github.com/mozilla/geckodriver/releases
# 20.1 has a bug where headless doesn't work
# 19 has a bug where it closes a frame?
# safari
# edge
# https://developer.microsoft.com/en-us/microsoft-edge/tools/webdriver/
logger.trace("createDriver()")
if browser.upper() == 'FIREFOX':
## setting log_path to /dev/null will prevent geckodriver from creating it's own log file.
## if we enable root logging, we can capture the logging from geckodriver, ourselves.
options = webdriver.FirefoxOptions()
profile = webdriver.FirefoxProfile()
profile.set_preference('app.update.auto', False)
profile.set_preference('app.update.enabled', False)
# options.binary_location = binary ## use this only if we want to move the executable outside the available path
if headless:
options.headless = True
caps = DesiredCapabilities.FIREFOX
caps['unhandledPromptBehavior'] = "ignore"
driver = webdriver.Firefox(profile, log_path='/dev/null', firefox_options=options,
desired_capabilities=caps
)
logger.debug(f"Driver info: firefox={driver.capabilities['browserVersion']}")
logger.debug(f"Session info: firefox={driver.capabilities['moz:geckodriverVersion']}")
if driver.capabilities['moz:geckodriverVersion'] == '0.20.1':
if headless:
raise Exception("Headless mode doesn't work in Gecko Driver 0.20.1")
elif browser.upper() == 'CHROME':
options = webdriver.ChromeOptions()
options.add_argument("--disable-extensions")
options.add_argument("--allow-running-insecure-content")
options.add_argument("--ignore-certificate-errors")
options.add_argument("--disable-single-click-autofill")
options.add_argument("--disable-autofill-keyboard-accessory-view[8]")
options.add_argument("--disable-full-form-autofill-ios")
options.add_argument("--dns-prefetch-disable") # https://bugs.chromium.org/p/chromedriver/issues/detail?id=402#c128
## ChromeDriver is just AWFUL because every version or two it breaks unless you pass cryptic arguments
options.add_argument("start-maximized") #
options.add_argument("enable-automation") #
options.add_argument("--no-sandbox") #
options.add_argument("--disable-infobars") #
options.add_argument("--disable-dev-shm-usage") #
options.add_argument("--disable-browser-side-navigation") #
options.add_argument("--disable-gpu") #
# options.add_argument("--window-size=1280,960")
options.add_argument("--enable-features=NetworkService,NetworkServiceInProcess") # https://groups.google.com/forum/m/#!topic/chromedriver-users/ktp-s_0M5NM[21-40]
if headless:
options.headless = True
# options.add_argument('--disable-gpu')
args = [
"--verbose"
]
caps = DesiredCapabilities.CHROME
caps['loggingPrefs'] = {
'browser': 'OFF',
'performance' : 'OFF',
'driver' : 'OFF'
}
# https://www.skptricks.com/2018/08/timed-out-receiving-message-from-renderer-selenium.html
# caps['pageLoadStrategy'] = 'none'
# caps['pageLoadStrategy'] = 'normal'
if consolelog:
caps['loggingPrefs']['browser'] = 'ALL'
## by default performance is disabled.
if performancelog:
caps['loggingPrefs']['performance'] = 'ALL'
caps['perfLoggingPrefs'] = {
'enableNetwork' : True,
'enablePage' : False,
'enableTimeline' : False
}
if verbose:
driver = webdriver.Chrome(options=options, service_log_path='chromedriver.log', service_args=args,
desired_capabilities=caps
)
else:
driver = webdriver.Chrome(options=options,
# service_log_path='chromedriver.log',
desired_capabilities=caps
)
logger.debug(f"Driver info: chrome={driver.capabilities['chrome']['chromedriverVersion']}")
logger.debug(f"Session info: chromedriver={driver.capabilities['version']}")
elif browser.upper() == 'EDGE':
# driver = webdriver.Edge()
raise NotImplemented("Edge not supported yet")
elif browser.upper() == 'SAFARI':
# driver = webdriver.Safari()
raise NotImplemented("Safari not supported yet")
# support is depricated for this -- should use chrome or firefox headless.
elif browser.upper() == 'PHANTOMJS':
# driver = webdriver.PhantomJS()
raise NotImplemented("PhantomJS not supported yet")
else:
raise ValueError(f"Unknown browser: {browser}")
# driver.set_page_load_timeout(self.timeout)
# driver.set_script_timeout(self.timeout)
return driver
在这两种情况下,驱动程序都位于处理自动退出驱动程序的包装器中。
############################################################################
def close(self):
if self.driver is not None:
self.driver.close()
############################################################################
def quit(self):
if self.driver is not None:
self.driver.quit()
############################################################################
def __del__(self):
self.quit()
在退出脚本之前调用 close 或 quit 不会触发让我感到困惑的错误消息。我原以为错误消息是垃圾收集时 geckodriver 中的某些内容,但如果是这种情况,我认为我可以通过在 sys.exit().
之前关闭驱动程序来手动触发错误任何人都知道在 firefox selenium 运行 之后此错误消息的来源?
编辑:
看起来有问题的文件夹是 FirefoxProfile
创建的临时目录。我认为 firefox.WebDriver.quit()
方法是日志行的来源。
def quit(self):
"""Quits the driver and close every associated window."""
try:
RemoteWebDriver.quit(self)
except Exception:
# We don't care about the message because something probably has gone wrong
pass
if self.w3c:
self.service.stop()
else:
self.binary.kill()
if self.profile is not None:
try:
shutil.rmtree(self.profile.path)
if self.profile.tempfolder is not None:
shutil.rmtree(self.profile.tempfolder)
except Exception as e:
print(str(e)) #<-- this is the line where the error occurs.
啊!我完全忘记了我向 Firefox webdriver 添加了一个 __del__
方法。 (这是在我编写包装器之前)
# hack to force firefox to quit when closing scope
def __del_replacement__(self: webdriver.Firefox):
print("__del__ called in Firefox")
self.quit()
webdriver.Firefox.__del__ = __del_replacement__
问题是 webdriver 的包装器中还有一个 __del__
方法,它也试图调用 driver.quit()
。问题是由两次调用 quit()
方法试图删除临时目录引起的。第二个失败了,因为它已经被删除了。