连接池已满,通过Selenium和Python丢弃与ThreadPoolExecutor和多个无头浏览器的连接

2023-12-07

我正在使用编写一些自动化软件selenium==3.141.0, python 3.6.7, chromedriver 2.44.

大多数逻辑可以由单个浏览器实例执行,但对于某些部分,我必须启动 10-20 个实例才能获得不错的执行速度。

一旦涉及到执行的部分ThreadPoolExecutor,浏览器交互开始抛出此错误:

WARNING|05/Dec/2018 17:33:11|connectionpool|_put_conn|274|Connection pool is full, discarding connection: 127.0.0.1
WARNING|05/Dec/2018 17:33:11|connectionpool|urlopen|662|Retrying (Retry(total=2, connect=None, read=None, redirect=None, status=None)) after connection broken by 'ProtocolError('Connection aborted.', RemoteDisconnected('Remote end closed connection without response',))': /session/119df5b95710793a0421c13ec3a83847/url
WARNING|05/Dec/2018 17:33:11|connectionpool|urlopen|662|Retrying (Retry(total=1, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NewConnectionError('<urllib3.connection.HTTPConnection object at 0x7fcee7ada048>: Failed to establish a new connection: [Errno 111] Connection refused',)': /session/119df5b95710793a0421c13ec3a83847/url

浏览器设置:

def init_chromedriver(cls):
    try:
        chrome_options = webdriver.ChromeOptions()
        chrome_options.add_argument('--headless')
        chrome_options.add_argument(f"user-agent={Utils.get_random_browser_agent()}")
        prefs = {"profile.managed_default_content_settings.images": 2}
        chrome_options.add_experimental_option("prefs", prefs)

        driver = webdriver.Chrome(driver_paths['chrome'],
                                       chrome_options=chrome_options,
                                       service_args=['--verbose', f'--log-path={bundle_dir}/selenium/chromedriver.log'])
        driver.implicitly_wait(10)

        return driver
    except Exception as e:
        logger.error(e)

相关代码:

ProfileParser实例化一个网络驱动程序并执行一些页面交互。我认为交互本身并不相关,因为一切都可以在没有ThreadPoolExecutor。 然而,简而言之:

class ProfileParser(object):
    def __init__(self, acc):
        self.driver = Utils.init_chromedriver()
    def __exit__(self, exc_type, exc_val, exc_tb):
        Utils.shutdown_chromedriver(self.driver)
        self.driver = None

    collect_user_info(post_url)
           self.driver.get(post_url)
           profile_url = self.driver.find_element_by_xpath('xpath_here')]').get_attribute('href')

当运行时ThreadPoolExecutor,此时出现上面的错误self.driver.find_element_by_xpath or at self.driver.get

这是工作:

with ProfileParser(acc) as pparser:
        pparser.collect_user_info(posts[0])

这些选项不起作用: (connectionpool errors)

futures = []
#one worker, one future
with ThreadPoolExecutor(max_workers=1) as executor:
        with ProfileParser(acc) as pparser:
            futures.append(executor.submit(pparser.collect_user_info, posts[0]))

#10 workers, multiple futures
with ThreadPoolExecutor(max_workers=10) as executor:
    for p in posts:
        with ProfileParser(acc) as pparser:
            futures.append(executor.submit(pparser.collect_user_info, p))

UPDATE:

我找到了一个临时解决方案(这不会使这个最初的问题无效) - 实例化一个webdriver在外面ProfileParser班级。不知道为什么它有效,但最初却不起作用。我想是某些语言细节的原因? 感谢您的回答,但问题似乎不是出在ThreadPoolExecutor max_workers限制 - 正如您在其中一个选项中看到的那样,我尝试提交单个实例,但它仍然不起作用。

目前的解决方法:

futures = []
with ThreadPoolExecutor(max_workers=10) as executor:
    for p in posts:
        driver = Utils.init_chromedriver()
        futures.append({
            'future': executor.submit(collect_user_info, driver, acc, p),
            'driver': driver
        })

for f in futures:
    f['future'].done()
    Utils.shutdown_chromedriver(f['driver'])

这个错误信息...

WARNING|05/Dec/2018 17:33:11|connectionpool|_put_conn|274|Connection pool is full, discarding connection: 127.0.0.1
WARNING|05/Dec/2018 17:33:11|connectionpool|urlopen|662|Retrying (Retry(total=2, connect=None, read=None, redirect=None, status=None)) after connection broken by 'ProtocolError('Connection aborted.', RemoteDisconnected('Remote end closed connection without response',))': /session/119df5b95710793a0421c13ec3a83847/url
WARNING|05/Dec/2018 17:33:11|connectionpool|urlopen|662|Retrying (Retry(total=1, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NewConnectionError('<urllib3.connection.HTTPConnection object at 0x7fcee7ada048>: Failed to establish a new connection: [Errno 111] Connection refused',)': /session/119df5b95710793a0421c13ec3a83847/url

...似乎是一个问题urllib3的连接池引发了这些WARNING执行时def _put_conn(self, conn)中的方法连接池.py.

def _put_conn(self, conn):
    """
    Put a connection back into the pool.

    :param conn:
        Connection object for the current host and port as returned by
        :meth:`._new_conn` or :meth:`._get_conn`.

    If the pool is already full, the connection is closed and discarded
    because we exceeded maxsize. If connections are discarded frequently,
    then maxsize should be increased.

    If the pool is closed, then the connection will be closed and discarded.
    """
    try:
        self.pool.put(conn, block=False)
        return  # Everything is dandy, done.
    except AttributeError:
        # self.pool is None.
        pass
    except queue.Full:
        # This should never happen if self.block == True
        log.warning(
            "Connection pool is full, discarding connection: %s",
            self.host)

    # Connection never got put back into the pool, close it.
    if conn:
        conn.close()

线程池执行器

线程池执行器 is an Executor使用线程池异步执行调用的子类。当与 Future 关联的可调用对象等待另一个 Future 的结果时,可能会发生死锁。

class concurrent.futures.ThreadPoolExecutor(max_workers=None, thread_name_prefix='', initializer=None, initargs=())
  • Executor 子类,使用最多 max_workers 线程池来异步执行调用。
  • 初始化程序是一个可选的可调用对象,在每个工作线程启动时调用; initargs 是传递给初始化器的参数元组。如果初始化程序引发异常,则所有当前挂起的作业以及向池中提交更多作业的任何尝试都将引发 BrokenThreadPool。
  • 从版本 3.5 开始:如果 max_workers 为 None 或未给定,则它将默认为机器上的处理器数量乘以 5,假设 ThreadPoolExecutor 通常用于重叠 I/O 而不是 CPU 工作,并且工作线程数应为高于 ProcessPoolExecutor 的工作线程数量。
  • 从版本 3.6 开始:添加了 thread_name_prefix 参数,以允许用户控制线程池创建的工作线程的线程名称,以便于调试。
  • 从版本 3.7 开始:添加了初始化程序和 initargs 参数。

根据您的问题,您尝试启动 10-20 个实例默认连接池大小 of 10在你的情况下似乎还不够,这是硬编码的适配器.py.

此外,@EdLeafe 在讨论中出现错误:连接池已满,正在丢弃连接提到:

看起来在请求代码中, None 对象是正常的。如果_get_conn() gets None从池中,它只是创建一个新连接。不过,这似乎很奇怪,它应该从所有这些 None 对象开始,并且 _put_conn() 不够智能,无法用连接替换 None 。

然而合并将池大小参数添加到客户端构造函数已经解决了这个问题。

Solution

增加默认连接池大小 of 10这是之前硬编码的适配器.py现在可配置将解决您的问题。


Update

根据您的评论更新...提交单个实例,结果是相同的...。根据讨论中的@meferguson84出现错误:连接池已满,正在丢弃连接:

我进入了代码,直到它安装了适配器,只是为了调整池大小,看看它是否会产生影响。我发现队列中充满了 NoneType 对象,实际上传连接是列表中的最后一项。该列表有 10 项长(这是有道理的)。没有意义的是,池的 unfinished_tasks 参数是 11。当队列本身只有 11 个项目时,怎么会这样呢?另外,队列中充满 NoneType 对象,而我们使用的连接是列表中的最后一项,这是否正常?

这听起来可能是你的原因usecase以及。这可能听起来多余,但您仍然可以执行一些临时步骤,如下所示:

  • Clean your 项目工作区通过你的IDE and Rebuild您的项目仅具有所需的依赖项。
  • (仅限 Windows 操作系统) Use CCleaner工具可以清除执行之前和之后的所有操作系统杂务测试套件.
  • (仅限 Linux 操作系统) 释放 Ubuntu/Linux Mint 中未使用/缓存的内存在执行你的之前和之后测试套件.
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

连接池已满,通过Selenium和Python丢弃与ThreadPoolExecutor和多个无头浏览器的连接 的相关文章

  • 在PyGI中获取窗口句柄

    在我的程序中 我使用 PyGObject PyGI 和 GStreamer 在 GUI 中显示视频 该视频显示在Gtk DrawingArea因此我需要获取它的窗口句柄realize 信号处理程序 在 Linux 上 我使用以下方法获取该句
  • 2d 图像点和 3d 网格之间的交点

    Given 网格 源相机 我有内在和外在参数 图像坐标 2d Output 3D 点 是从相机中心发出的光线穿过图像平面上的 2d 点与网格的交点 我试图找到网格上的 3d 点 This is the process From Multip
  • 通过 boto3 承担 IAM 用户角色时访问被拒绝

    Issue 我有一个 IAM 用户和一个 IAM 角色 我正在尝试将 IAM 用户配置为有权使用 STS 承担 IAM 角色 我不确定为什么收到 访问被拒绝 错误 Details IAM 角色 arn aws iam 123456789 r
  • 将 yerr/xerr 绘制为阴影区域而不是误差线

    在 matplotlib 中 如何将误差绘制为阴影区域而不是误差条 例如 而不是 忽略示例图中各点之间的平滑插值 这需要进行一些手动插值 或者只是获得更高分辨率的数据 您可以使用pyplot fill between https matpl
  • 从字典的元素创建 Pandas 数据框

    我正在尝试从字典创建一个 pandas 数据框 字典设置为 nvalues y1 1 2 3 4 y2 5 6 7 8 y3 a b c d 我希望数据框仅包含 y1 and y2 到目前为止我可以使用 df pd DataFrame fr
  • 将 C++ 指针作为参数传递给 Cython 函数

    cdef extern from Foo h cdef cppclass Bar pass cdef class PyClass cdef Bar bar def cinit self Bar b bar b 这总是会给我类似的东西 Can
  • 为什么第二个 request.session cookies 返回空?

    我想使用 requests Session post 登录网站 但是当我已经登录主页 然后进入帐户页面时 看来cookies还没有保存 因为cookies是空的 而且我无法进入正确的帐户页面 import requests from bs4
  • 如何获取numpy.random.choice的索引? - Python

    是否可以修改 numpy random choice 函数以使其返回所选元素的索引 基本上 我想创建一个列表并随机选择元素而不进行替换 import numpy as np gt gt gt a 1 4 1 3 3 2 1 4 gt gt
  • 将 pandas 剪切操作转换为常规字符串

    我明白了 pandas cut 操作的输出 0 0 20 1 0 20 2 0 20 3 0 20 4 0 20 5 0 20 6 0 20 7 0 20 8 0 20 9 0 20 如何将 0 20 转换为 0 20 我正在这样做 str
  • 如何将 sql 数据输出到 QCalendarWidget

    我希望能够在日历小部件上突出显示 SQL 数据库中的一天 就像启动程序时突出显示当前日期一样 在我的示例中 它是红色突出显示 我想要发生的是 当用户按下突出显示的日期时 数据库中日期旁边的文本将显示在日历下方的标签上 这是我使用 QT De
  • python celery -A 的无效值无法加载应用程序

    我有一个以下项目目录 azima init py main py tasks py task py from main import app app task def add x y return x y app task def mul
  • 在 Mac OS X 上安装 libxml2 时出现问题

    我正在尝试在我的 Mac 操作系统 10 6 4 上安装 libxml2 我实际上正在尝试在 Python 中运行 Scrapy 脚本 这需要我安装 Twisted Zope 现在还需要安装 libxml2 我已经下载了最新版本 2 7 7
  • Jupyter 笔记本中未显示绘图图表

    我已经尝试解决这个问题几个小时了 我按照上面的步骤操作情节网站 https plot ly python getting started start plotting online并且图表仍然没有显示在笔记本中 这是我的情节代码 color
  • 为正则表达式编写解析器

    即使经过多年的编程 我很羞愧地说我从未真正完全掌握正则表达式 一般来说 当问题需要正则表达式时 我通常可以 在一堆引用语法之后 想出一个合适的正则表达式 但我发现自己越来越频繁地使用这种技术 所以 自学并理解正则表达式properly 我决
  • Discord.py 嵌入中禁用按钮/冻结按钮

    I m trying to make a replica of this bot in which when I press any of the buttons below it shows a dropdown menu and you
  • 使用 selenium 和 python 来提取 javascript 生成的 HTML?萤火虫?

    这里是Python新手 我遇到的是数据收集问题 我在这个网站上 当我用 Firebug 检查我想要的元素时 它显示了包含我需要的信息的源 然而常规源代码 没有 Firebug 不会给我这个信息 这意味着我也无法通过正常的 selenium
  • numpy polyfit 中使用的权重值是多少以及拟合误差是多少

    我正在尝试对 numpy 中的某些数据进行线性拟合 Ex 其中 w 是该值的样本数 即对于点 x 0 y 0 我只有 1 个测量值 该测量值是2 2 但对于这一点 1 1 我有 2 个测量值 值为3 5 x np array 0 1 2 3
  • 仅允许正小数

    在我的 Django 模型中 我创建了一个如下所示的小数字段 price models DecimalField u Price decimal places 2 max digits 12 显然 价格为负或零是没有意义的 有没有办法将小数
  • 非法指令:MacOS High Sierra 上有 4 条指令

    我正在尝试在 pygame 3 6 中制作一个看起来像聊天的窗口 我刚刚将我的 MacBook 更新到版本 10 13 6 在我这样做之前它工作得很好 但在我收到消息之后 非法指令 4 Code import pygame from pyg
  • 在matlab中,如何读取python pickle文件?

    在 python 中 我生成了一个 p 数据文件 pickle dump allData open myallData p wb 现在我想在Matlab中读取myallData p 我的Matlab安装在Windows 8下 其中没有Pyt

随机推荐