【问题标题】:Selenium using too much RAM with FirefoxSelenium 在 Firefox 中使用过多 RAM
【发布时间】:2019-07-31 01:08:56
【问题描述】:

我在 Firefox 中使用 selenium 来自动化 Instagram 上的一些任务。它基本上在用户个人资料和通知页面之间来回切换,并根据找到的内容执行任务。

它有一个无限循环,可确保任务继续进行。我每隔几步就有 sleep() 函数,但内存使用量不断增加。我在 Python 中有这样的东西:

while(True):
    expected_conditions()
    ...doTask()
    driver.back()
    expected_conditions()
    ...doAnotherTask()
    driver.forward()
    expected_conditions()

我从不关闭驱动程序,因为这会大大降低程序的速度,因为它需要处理很多查询。有什么办法可以在不关闭或退出驱动的情况下防止内存使用量增加超时?

编辑:添加了明确的条件,但这也无济于事。我正在使用 Firefox 的无头模式。

【问题讨论】:

  • 尽量避免使用 sleep 方法,使用 Explicit Waits 或 Implicit Waits 方法更多信息请参见selenium-python.readthedocs.io/waits.html
  • 好的。明天我会尝试这样做,并在此处发布发现。
  • sleep() 更改为等待不会改变 任何关于:内存使用情况。不使用睡眠的原因是因为这会硬编码脚本不做任何事情的时间间隔,希望页面会改变状态;并且使用 *Wait 间隔不是硬编码的,而是“一旦发生变化”。在您的用例中,听起来确实像您使用 sleep() 作为执行之间的分隔符,并且在无限循环中运行,您听起来并不需要减少几秒钟的时间。

标签: python selenium firefox geckodriver selenium-firefoxdriver


【解决方案1】:
  • 使用显式等待或隐式等待。
  • 使用 driver.quit() 关闭所有 浏览器窗口并终止 WebDriver 会话,因为如果 你不要在程序结束时使用quit(),WebDriver 会话不会正确关闭,文件不会被清除 没有记忆。这可能会导致内存泄漏错误。

【讨论】:

  • 添加显式等待没有帮助,它仍然是同一个故事。内存使用量不断增加。我确实找到了一个临时解决方法,方法是在关闭/退出驱动程序之前添加一个内部循环运行 X 次,无限循环再次启动驱动程序并再次进入该循环。它确实可以防止它耗尽所有内存,但这不是一个合适的解决方案。
  • 你用过driver.quit()吗?
  • 是的。做了 driver.close() 然后 driver.quit()
【解决方案2】:

创建新的 Firefox 配置文件并在每次在 Firefox 中运行测试用例时使用它最终会提高执行性能,因为如果不这样做,总是会创建新的配置文件并在那里完成缓存信息,如果 driver.quit 没有得到在失败之前以某种方式调用,然后在这种情况下,每次我们最终都会使用一些缓存信息创建新配置文件,这会消耗内存。

// ------------ 创建一个新的 firefox 配置文件 --------

1. If Firefox is open, close Firefox.
2. Press Windows +R on the keyboard. A Run dialog will open.
3. In the Run dialog box, type in firefox.exe -P
Note: You can use -P or -ProfileManager(either one should work).
4. Click OK.
5. Create a new profile and sets its location to the RAM Drive.

// ----------- 关联 Firefox 配置文件 -------

ProfilesIni profile = new ProfilesIni();
FirefoxProfile myprofile = profile.getProfile("automation_profile");
WebDriver driver = new FirefoxDriver(myprofile);

如果您打算以这种方式实施,请与社区分享执行绩效。

【讨论】:

  • 我正在使用无头模式。使用不同的个人资料会很重要吗?
  • 我还是会说是的,你应该试一试。因为缓存信息也应该是无头模式下配置文件管理的一部分。除此之外,我想分享一下,Mozilla Firefox 的 headless 模式比 UI 版本的表现要好 3.68%。这是令人失望的,因为 Chrome 的无头模式比 UI 模式的时间快了 30% 以上。
【解决方案3】:

Selenium 开始,对 Firefox 使用的 RAM 数量几乎没有控制。正如您提到的 Browser ClientMozillaInstagram 上的用户配置文件和通知页面之间来回切换,并根据它发现的内容执行任务作为单个用例过于宽泛。因此,首要任务是将与您的用例相关的无限循环分解为更小的测试


time.sleep()

诱导time.sleep() 实际上掩盖了根本问题。然而,在使用 SeleniumWebDriver 通过您的 Automation Framework 执行测试时,在没有任何特定条件的情况下使用 time.sleep() 会破坏自动化的目的,因此应在任何时候避免成本。根据文档:

time.sleep(secs) 将当前线程的执行挂起给定的秒数。该参数可以是一个浮点数,以指示更精确的睡眠时间。实际的挂起时间可能少于请求的时间,因为任何捕获的信号都会在执行该信号的捕获例程后终止 sleep()。此外,由于系统中其他活动的调度,暂停时间可能比请求的时间长。

您可以在How to sleep webdriver in python for milliseconds找到详细讨论


分析

Firefox 之前的一些实例消耗了大约 80% 的 RAM。

但是,根据this discussion,一些用户认为使用的内存越多越好,因为这意味着您不会浪费内存。 Firefox 使用 RAM 来加快处理速度,因为应用程序数据在 RAM 中的传输速度要快得多。


解决方案

您可以执行以下任一/所有通用/特定步骤:

  • Selenium升级到当前级别Version 3.141.59
  • GeckoDriver升级到GeckoDriver v0.24.0级别。
  • Firefox 版本升级到 Firefox v65.0.2 级别。
  • 清理你的项目工作区通过你的IDE重建你的项目只需要依赖。
  • 如果您的基本 Web 客户端 版本太旧,请卸载它并安装最新的 GA 和发布版本的 Web 客户端
  • 某些扩展程序允许您阻止此类不必要的内容,例如:

    • uBlock Origin 允许您在网站上隐藏广告。
    • NoScript 允许您有选择地启用和禁用网站上运行的所有脚本。
    • 要打开带有扩展名的 Firefox 客户端,您可以从 https://addons.mozilla.org 下载扩展名,即 XPI 文件,然后使用 add_extension(extension='webdriver.xpi') 方法将扩展名添加到 FirefoxProfile 如下:

      from selenium import webdriver
      
      profile = webdriver.FirefoxProfile() 
      profile.add_extension(extension='extension_name.xpi')
      driver = webdriver.Firefox(firefox_profile=profile, executable_path=r'C:\path\to\geckodriver.exe') 
      
  • 如果您的 Tests 不需要 CSS,您可以在 this discussion 之后禁用 CSS

【讨论】:

  • 嗨。驱动程序、Firefox 和 Selenium 都是最新的。我的工作区是新的,但我再次清理并重建了它。它似乎并没有以任何方式影响性能。我也摆脱了 time.sleep 并使用 Selenium 中提供的显式条件我正在为 firefox 使用无头模式,css/脚本对此仍然很重要吗?
  • @NaeemKhan 这很重要。查看我的答案中关于禁用 CSS 的讨论。
  • FirefoxOptions() 中似乎没有 add_experimental_option() 函数。如何为 Firefox 禁用它?
  • 好的,我已经通过 firefoxProfile.set_preference('permissions.default.stylesheet', 2) 和图像禁用了 css。它仍然没有任何区别。 Ram 的使用量仍在增加。我认为问题可能在于 Instagram 大量使用 javascript 和 AJAX?
  • 它仍然没有解决问题,但它是最接近我的问题,所以我会接受答案。
【解决方案4】:

目前还没有解决方法。 我建议你使用 driver.close() 方法。 我也在努力解决 RAM 问题,我所做的是计算循环数,当循环数达到一定数量(对我来说是 200)时,我调用 driver.close() 然后再次启动驱动程序并重置计数。 这样我就不需要每次执行循环时都关闭驱动程序,并且对性能的影响也较小。 尝试这个。也许它对你的情况也有帮助。

【讨论】:

  • 这为我解决了问题。可悲的是,对我来说这个数字要小得多(~25),但我认为这高度依赖于站点和您的本地计算机。
【解决方案5】:

嗯,这是我几天来一直在经历的严重问题。但我找到了解决方案。您可以添加一些标志来优化内存使用。

options = Options()
options.add_argument("start-maximized")
options.add_argument("disable-infobars")
options.add_argument("--disable-extensions")
options.add_argument('--no-sandbox')
options.add_argument('--disable-application-cache')
options.add_argument('--disable-gpu')
options.add_argument("--disable-dev-shm-usage")

这些是我添加的标志。在我添加标志之前,RAM 使用量在超过 4GB(我的机器为 8GB)后不断增加,我的机器卡住了。添加这些标志后,内存使用量没有超过 500MB。正如 DebanjanB 所回答的那样,如果您运行 for loopwhile loop 尝试在每次执行后休眠几秒钟,它将给一些时间来杀死未使用的线程。

【讨论】:

  • 我很确定这很有帮助,值得更多的支持。一个问题。您说您将内存保持在 50 MB 以下?对我来说,它一直低于 500 MB。是您的错字还是内存使用量高出 10 倍?
  • 是的,抱歉,我改了,谢谢
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-12-15
  • 1970-01-01
  • 2021-11-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多