在我的应用程序中,我在线程中发送多个 request.post()
请求。根据我必须发布的数据量,创建的线程数量可能有数百个。
request
对象的实际创建是使用requests-oauthlib
完成的,它在使用时将身份验证数据插入到request
对象中.
我的问题是,当并行发送大量数据时,日志中会充斥着以下消息,并且最终不再有输入发送到日志:
连接池已满。正在放弃连接。
我的问题是,通过使用 requests-oauthlib
,有没有一种方法可以指定连接池的大小,也许在 post
方法本身内,或者是否应该阻止,以便其他请求可以在创建更多请求之前完成?我要求这样做是因为使用 requests-oauthlib
时,构建自定义 request
对象会很棘手,并询问 requests-oauthlib
使用它。
我尝试过的一件事如下,但没有效果 - 我继续收到警告:
import requests
s = requests.Session()
a = requests.adapters.HTTPAdapter(pool_block=True)
s.mount('http://', a)
s.mount('https://', a)
更新 - 现在正在以受控方式创建线程。
with futures.ThreadPoolExecutor(max_workers=10) as executor:
executor.submit(function, args)
最佳答案
阻止请求以便只有 N 个请求同时尝试使用连接池的最简单方法是一次仅创建 N 个。
最简单的方法是使用一个由 N 个线程组成的池来为 M 个请求的队列提供服务,而不是为每个请求使用单独的线程。如果您使用的是 Python 3.2+,则使用 concurrent.futures
非常容易。事实上,它与第一个 ThreadPoolExecutor 示例几乎相同,只是您使用的是 requests 而不是 urllib。如果您不使用 3.2+,则有一个名为 futures
的 stdlib 模块的向后移植。它提供了与…我认为 2.6 相同的功能,但不要引用我的话(PyPI 目前已关闭)。
可能有一个更简单的解决方案:有一个名为 requests-futures
的第三方库我从名字中猜测(再次,PyPI 下来了……),以某种方式为你包装了它。
您可能还想考虑使用类似 grequests
的内容使用 gevent
greenlet 在一个线程中完成这一切,但就您的代码而言,这与使用线程池没有显着不同。
关于Python 请求 URLLib3 连接池大小,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26083489/