如何为多进程池中的单个进程分配Python请求会话?

6
考虑以下代码示例:
import multiprocessing
import requests

session = requests.Session()
data_to_be_processed = [...]

def process(arg):
    # do stuff with arg and get url
    response = session.get(url)
    # process response and generate data...
    return data

with multiprocessing.Pool() as pool:
    results = pool.map(process, data_to_be_processed)

举个例子,Session 被分配为全局变量,因此在创建 Pool 进程后,它将被复制到每个子进程中。我不确定 session 是否线程安全,也不知道如何在 session 中使用池,所以我想为池中的每个进程分配单独的 session 对象
我知道可以只使用 requests.get(url) 而不是 session.get(url),但我想使用 session,并且我也考虑使用 requests-html (https://html.python-requests.org/)。
我对 Python 的多进程技术不是很熟悉,到目前为止,我只使用过 pool,因为它是处理数据并行化且无需关键部分的最佳解决方案,因此我可以接受不同的解决方案。
有没有一种干净而直观的方法来做到这一点?

如果您在会话中有多个调用,则会话才有意义。我只看到一个。 - Klaus D.
你为什么需要一个Session(相对于只使用requests.get())? - Klaus D.
我将要查询的所有网址都在同一个网站上,因此我认为这将为我的程序和网站服务器节省一些处理时间。 - Nixwill
在multiprocessing.Pool()的initializer参数中定义会话,可以为您提供所需的内容,即每个进程一个会话。 - cylim
@cylim,但如何从池中重用会话? - Konstantin Glukhov
显示剩余3条评论
1个回答

1

简短回答:您可以使用全局命名空间在initializerfunc之间共享数据:

import multiprocessing
import requests

session = None
data_to_be_processed = [...]

def init_process():
    global session
    session = requests.Session()

def process(arg):
    global session
    # do stuff with arg and get url
    response = session.get(url)
    # process response and generate data...
    return data

with multiprocessing.Pool(initializer=init_process) as pool:
    results = pool.map(process, data_to_be_processed)

长答案: Python 使用三种可能的 启动方法 之一。所有这些方法都在父进程和子进程之间分离内存对象。在我们的情况下,这意味着由 Pool() 运行的进程的全局命名空间中的更改不会传播回父进程,也不会传播到同级进程。
对于对象销毁,我们可以依靠垃圾收集器,在子进程完成其工作后介入。在 multiprocessing.Pool() 中缺乏显式关闭方法,这使得它无法与不可通过 GC(例如 Pool() 本身 - 请参见此处的警告here)销毁的对象一起使用。 从 requests docs 的判断来看,使用 requests.Session 而不显式调用 close() 是完全可以的。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接