在Python中使用多处理将项追加到列表
在这段代码中:在Python中使用多处理将项追加到列表,python,multiprocessing,Python,Multiprocessing,在这段代码中: def get_spain_accomodations(): pool = Pool() links = soup.find_all('a', class_="hotel_name_link url") pool.map(get_page_links, links) #for a in soup.find_all('a', class_="hotel_name_link url"): # hotel_url = "https://w
def get_spain_accomodations():
pool = Pool()
links = soup.find_all('a', class_="hotel_name_link url")
pool.map(get_page_links, links)
#for a in soup.find_all('a', class_="hotel_name_link url"):
# hotel_url = "https://www.booking.com" + a['href'].strip()
# hotels_url_list.append(hotel_url)
def get_page_links(link):
hotel_url = "https://www.booking.com" + link['href'].strip()
hotels_url_list.append(hotel_url)
由于某些原因,没有将hotel_url附加到列表中。如果我尝试使用注释循环,它实际上是有效的,但不适用于map()函数。我还为每个get_page_links电话打印了酒店的url,这很有效。我不知道发生了什么事。下面是函数调用
init_BeautifulSoup()
get_spain_accomodations()
#get_hotels_wifi_rating()
for link in hotels_url_list:
print link
代码执行时没有错误,但链接列表没有打印。了解进程在内存的隔离区域中运行是很重要的。每个进程都有自己的实例
hotels\u url\u list
,没有(简单的)方法将这些值“粘贴”到父进程的列表中:如果在父进程中创建list
的实例,则该实例与子进程使用的实例不同:当您执行.fork()
(也称为创建子进程),父进程的内存在子进程上被克隆。因此,如果父进程在hotels\u url\u list
变量中有一个list
的实例,您还将有一个list
的实例(也称为hotels\u url\u list
)在子进程中,但它们将不相同(它们将占用内存中的不同区域)
线程不会发生这种情况。它们确实共享内存
我想说(我不是这里的专家),在这种情况下,传递进程的标准方式是:子进程将事物放入队列,父进程将它们捕获:
from multiprocessing import Process, Queue
def get_spain_accomodations():
q = Queue()
processes = []
links = ['http://foo.com', 'http://bar.com', 'http://baz.com']
hotels_url_list = []
for link in links:
p = Process(target=get_page_links, args=(link, q,))
p.start()
processes.append(p)
for p in processes:
p.join()
hotels_url_list.append(q.get())
print("Collected: %s" % hotels_url_list)
def get_page_links(link, q):
print("link==%s" % link)
hotel_url = "https://www.booking.com" + link
q.put(hotel_url)
if __name__ == "__main__":
get_spain_accomodations()
这将输出带有https://www.booking.com
,独立进程上发生的预挂起:
link==http://foo.com
link==http://bar.com
link==http://baz.com
Collected: ['https://www.booking.comhttp://foo.com', 'https://www.booking.comhttp://bar.com', 'https://www.booking.comhttp://baz.com']
我不知道这是否对您有帮助,但对我来说,它有助于将队列视为“共享文件”这两个进程都知道。假设你有两个完全不同的程序,其中一个知道必须将内容写入一个名为/tmp/foobar.txt
的文件,另一个知道必须从一个名为/tmp/foobar.txt
的文件中读取内容。这样,它们可以相互“通信”。这一段只是一个例子“隐喻”(虽然这就是工作原理)…不像队列那样工作,但也许它有助于理解这个概念?不知道,真的,也许我把它弄得更混乱了
另一种方法是使用线程并收集它们的返回值,如前所述。在进程之间共享状态并不简单。为什么不使用
pool.map
创建列表呢?换句话说,不要执行hotels\u url\u list.append(hotel\u url)
,只需从获取页面链接返回酒店url
,然后保存pool.map(…)