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

时间:2018-10-09 13:32:49

标签: python python-3.x session python-requests python-multiprocessing

考虑以下代码示例:

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中创建进程后,它将被复制到每个子进程中。我不确定会话是否是线程安全的,也不知道会话中的池如何工作,因此我想为池中的每个进程分配单独的会话对象

我知道,我可以只使用requests.get(url)而不是session.get(url),但是我想使用会话,并且我还在考虑使用requests-htmlhttps://html.python-requests.org/ )。

我对python的多处理不是很熟悉,到目前为止,我仅使用pool,因为它是我在没有关键部分的情况下并行处理数据的最佳解决方案,因此我愿意接受不同的解决方案。

有没有一种方法可以使它简洁明了?

1 个答案:

答案 0 :(得分:0)

简短答案:您可以使用全局名称空间在初始化器 func 之间共享数据:

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使用三种可能的start methods中的一种。它们全部在父进程和子进程之间分隔内存对象。在我们的情况下,这意味着 Pool()运行的进程的全局名称空间中的更改将不会传播回父进程,也不会传播到同级进程。

对于对象销毁,我们可以依靠垃圾收集器,该垃圾收集器会在子进程完成工作后介入。 multiprocessing.Pool()中没有显式关闭方法,使得无法使用无法被GC破坏的对象(例如 Pool()本身-参见警告{{ 3}}) 从here来看,完全可以使用 requests.Session ,而无需在其上使用明确的close()。