python中的并行处理以将字典值填充为字典(嵌套)

时间:2020-06-01 11:07:45

标签: python dictionary parallel-processing multiprocessing python-multiprocessing

我在CSV文件中有多个链接(URL),我想使用这些URL提取/抓取数据并将其以字典格式存储。

为此,我开发了一个函数,该函数以URL作为输入,并返回字典作为输出。

例如:

def site_details(URL):

    site_dict = {}
    response = requests.get(url)
    soup = BeautifulSoup(response.content, 'html.parser')
    site_dict['Date_created'] = soup.find('div', attrs={"class":"date" })
    site_dict['visits'] = soup.find('div', attrs={"class":"visits" })
    return(site_dict)

现在,我想并行处理所有URL,并将它们存储在另一个字典中,然后可以将其转换为CSV文件。

到目前为止,我已经尝试了以下方法:

from multiprocess import Process, Manager
def f(d, x):
    d[x] = site_details(df["Subject_link"][x])
    return d

manager = Manager()
d = manager.dict()
job = [Process(target=f, args=(d, i)) for i in range(5)]

_ = [p.start() for p in job]
_ = [p.join() for p in job]
print(d)

问题是我得到的清单为空

我想要这样的输出:

d = {
      1:{date_created : '22/1/2014',visits:490}
      2:{date_created : '23/1/2014',visits:480}
      3:{date_created : '24/1/2014',visits:470}
    }

感谢您的帮助!

1 个答案:

答案 0 :(得分:0)

使用 multiprocessing 模块的此代码可以正常工作。
该代码应使用Mike McKearns的 multiprocess 来实现。

不起作用?

a)检查 dill 模块的存在,这是multiprocess正常工作的前提。

b)重新运行下面的代码。

c)根据需要调整此工作模板,但不要拒绝返回任何值,而是将其存储到由 Manager管理的实例变量中-实例,最好通过Manager子句将with Manager as myNewContextManagerForThisLimitedScopeOfUse:用作上下文管理器

from multiprocessing import Process, Manager                            # https://stackoverflow.com/questions/62130801/parallel-processing-in-python-to-fill-a-dictionary-with-the-value-as-a-dictionar
import os

def f( d, l, i ):
    d[0]    = '1'
    d['2']  =  2
    d[0.25] = None
    d[1] = { "date_created": '22/1/2014', "visits": 490, "os.getpid()": os.getpid() }
    d[2] = { "date_created": '23/1/2014', "visits": 480, "os.getpid()": os.getpid() }
    d[3] = { "date_created": '24/1/2014', "visits": 470, "os.getpid()": os.getpid() }
    d[99 + 100 * ( i + 1 )] = os.getpid()
    l.reverse()

if __name__ == '__main__':
    print( "The __main__ in PID::", os.getpid() )
    with Manager() as myDemoMANAGER:
        d = myDemoMANAGER.dict()
        l = myDemoMANAGER.list( range( 10 ) )

        # p = Process( target = f, args = ( d, l ) )
        # 
        # p.start()
        # p.join()

        jobs = [ Process( target = f, args = ( d, l, i ) ) for i in range( 5 ) ]
        _    = [ p.start() for p in jobs ]
        _    = [ p.join()  for p in jobs ]


        print( "The dict instance is: ", d )
        print( "The list instance is: ", l )
        print( "\nQ.E.D." )

'''
(py3) Tue Jun 02 13:49:27 $ python StackOverflow_py3_Multiprocess.py

The __main__ in PID:: 19595
The dict instance is:  { 0: '1',
                         0.25: None,
                         1: { 'date_created': '22/1/2014', 'visits': 490, 'os.getpid()': 19610 },
                         2: { 'date_created': '23/1/2014', 'visits': 480, 'os.getpid()': 19607 },
                         3: { 'date_created': '24/1/2014', 'visits': 470, 'os.getpid()': 19607 },
                         199: 19604,
                         299: 19605,
                         399: 19607,
                         499: 19609,
                         599: 19610,
                        '2': 2
                         }
The list instance is:  [ 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 ]

Q.E.D.

'''

关于修改托管对象内部详细信息的简短说明:

文档明确警告要修改v / s分配v / s重新分配托管对象:

如果引用中包含标准(非代理)listdict对象,则对那些可变值的修改不会通过manager传播因为代理无法知道何时修改其中包含的值。但是,将值存储在容器代理中(会触发代理对象上的 __setitem__ )会通过manager传播,因此要有效地修改此类项目,可以将修改后的值重新分配给容器代理