python - 完成 firefox selenium 测试后出现“没有这样的文件或目录”错误消息
问题描述
我在使用 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") # https://stackoverflow.com/a/26283818/1689770
options.add_argument("enable-automation") # https://stackoverflow.com/a/43840128/1689770
options.add_argument("--no-sandbox") # https://stackoverflow.com/a/50725918/1689770
options.add_argument("--disable-infobars") # https://stackoverflow.com/a/43840128/1689770
options.add_argument("--disable-dev-shm-usage") # https://stackoverflow.com/a/50725918/1689770
options.add_argument("--disable-browser-side-navigation") # https://stackoverflow.com/a/49123152/1689770
options.add_argument("--disable-gpu") # https://stackoverflow.com/questions/51959986/how-to-solve-selenium-chromedriver-timed-out-receiving-message-from-renderer-exc
# 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.
解决方案
呸!我完全忘记了我__del__
在 Firefox 网络驱动程序中添加了一个方法。(这是在我写包装之前)
# 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()
尝试删除临时目录的方法调用引起的。第二个失败了,因为它已经被删除了。
推荐阅读
- php - 我应该使用哪个 SQL 请求?
- javascript - 无法将选项值放入隐藏字段
- java - Google Analytics API - 最近失败的报告 API 请求数过多
- javascript - 这个 jQuery 插件不能识别波斯字母和数字。我的代码有问题吗?还是来自其他地方?
- javascript - 如何在 SVG 中的特定位置放置文本?
- bash - 如何在每次启动后运行 shell 脚本以检查是否已上传另一个播客?
- c# - 如何在 C# 中查看所选应用程序的所有注册表更改
- kotlin - Ktor - 如何在 Kotlin-Multiplatform 通用模块中使用纯 Kotlin 解码 base64 令牌?
- mysql - 如何将根 MySQL 系统用户限制为 GCP Cloud SQL 中的单个主机?
- vim - 更改文件类型上的 Vim 航空公司配色方案