【问题标题】:multiprocessing does not save data多处理不保存数据
【发布时间】:2023-03-12 10:23:01
【问题描述】:

我的程序基本上是从我制作的网站上抓取图像。我有 3 个函数,每个函数都使用参数从特定网站上抓取图像。我的程序包含以下代码。

import requests
from bs4 import BeautifulSoup
from multiprocessing import Process

img1 = []
img2 = []
img3 = []

def my_func1(img_search):
    del img1[:]

    url1 = "http://www.somewebsite.com/" + str(img_search)
    r1 = requests.get(url1)
    soup1 = BeautifulSoup(r1.content)
    data1 = soup1.find_all("div",{"class":"img"})

    for item in data1:
        try:
            img1.append(item.contents[0].find('img')['src'])
        except:
            img1.append("img Unknown")
    return

def my_func2(img_search):
    del img2[:]

    url2 = "http://www.somewebsite2.com/" + str(img_search)
    r2 = requests.get(url2)
    soup2 = BeautifulSoup(r2.content)
    data2 = soup2.find_all("div",{"class":"img"})

    for item in data2:
        try:
            img2.append(item.contents[0].find('img')['src'])
        except:
            img2.append("img Unknown")
    return

def my_func3(img_search):
    del img3[:]

    url3 = "http://www.somewebsite3.com/" + str(img_search)
    r3 = requests.get(url3)
    soup3 = BeautifulSoup(r3.content)
    data3 = soup3.find_all("div",{"class":"img"})

    for item in data3:
        try:
            img3.append(item.contents[0].find('img')['src'])
        except:
            img3.append("img Unknown")
    return

my_func1("orange cat")
my_func2("blue cat")
my_func3("green cat")

print(*img1, sep='\n')
print(*img2, sep='\n')
print(*img3, sep='\n')

抓取工作得很好,但速度很慢,所以我决定使用多处理来加快速度,而多处理确实加快了速度。我基本上用这个替换了函数调用

p = Process(target=my_func1, args=("orange cat",))
p.start()
p2 = Process(target=my_func2, args=("blue cat",))
p2.start()
p3 = Process(target=my_func3, args=("green cat",))
p3.start()

p.join()
p2.join()
p3.join()

但是,当我打印 img1 、 img2 和 img3 列表时,它们是空的。我该如何解决这个问题?

【问题讨论】:

    标签: python python-3.x beautifulsoup multiprocessing


    【解决方案1】:

    当您使用multiprocessing 在多个进程之间分配您的工作时,每个进程将在单独的命名空间(主进程的命名空间的副本)中运行。您在子进程的命名空间中所做的更改不会反映在父进程的命名空间中。您需要使用multiprocessing.Queue 或其他一些同步方法从工作进程传回数据。

    在您的示例代码中,您的三个函数几乎完全相同,只是网站的域和变量名称不同。如果这就是你的真实函数的样子,我建议使用 multiprocessing.Pool.map 并将整个 URL 传递给单个函数,而不是仅仅传递搜索词:

    def my_func(search_url):
        r = requests.get(search_url)
        soup = BeautifulSoup(r.content)
        data = soup.find_all("div",{"class":"img"})
        images = []
        for item in data:
            try:
                images.append(item.contents[0].find('img')['src'])
            except:
                images.append("img Unknown")
        return images
    
    if __name__ == "__main__":
        searches = ['http://www.somewebsite1.com/?orange+cat', # or whatever
                    'http://www.somewebsite2.com/?blue+cat',
                    'http://www.somewebsite3.com/?green+cat']
        pool = multiprocessing.Pool() # will create as many processes as you have CPU cores
        results = pool.map(my_func, searches)
        pool.close()
        # do something with results, which will be a list with of the function return values
    

    【讨论】:

    • 对于我的情况,我将如何使用队列将数据传递到我的列表?
    • 实际上,现在我查看了您的工作函数,我发现它们几乎相同。如果这不是对 Stack Overflow 的简化,我建议将它们替换为单个函数并使用 multiprocessing.Pool.mapPool 负责启动进程并为您设置队列。即使您确实需要单独的工作函数,也可以在 Pool 上使用 apply_async
    • 我目前正在使用此文档:docs.python.org/2/library/multiprocessing.html 寻求帮助。如果可以,请您演示一个简单的示例来指导我,不胜感激。谢谢。
    • 我已经编辑了我的答案,使用multiprocessing.Pool添加了一些(未经测试的)示例代码。
    • @SagwaTheCat:您可以使用使用线程而不是进程的multiprocessing.dummy.Pool。看看最适合你的情况。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-08-18
    • 1970-01-01
    • 1970-01-01
    • 2023-03-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多