基于multiprocessing的Python并发循环:网页链接处理问题咨询
问题解答与代码修正
3. 该任务是否适合使用multiprocessing?
非常适合。你的核心操作是网络请求(IO密集型任务),多进程可以利用CPU在等待网络响应的空闲时间处理其他请求,大幅提升整体处理效率。推荐使用multiprocessing.Pool(进程池),它会自动管理进程创建、任务分配和结果收集,比手动创建Process更简洁高效。
1. 进程间共享结果的正确方式
Python多进程之间内存是隔离的,直接让多个进程往同一个列表追加数据会失效(每个进程都有自己的列表副本)。正确做法是:
- 让每个进程处理单个链接后,返回该链接的分类结果
- 主进程统一收集所有结果,再将链接追加到对应的列表中
2. 进程间的链接分配
使用进程池的map/imap_unordered方法可以自动分配链接,无需手动拆分列表。进程池会根据CPU核心数,将任务均匀分配给各个子进程,避免重复处理同一链接。
修正后的完整代码
import os from multiprocessing import Pool def get_data_from_db(): # 替换为你的数据库读取逻辑 return [f"https://example.com/link{i}" for i in range(100)] def manage_requests(link): # 替换为你的请求处理逻辑 import bs4 if link.endswith('0'): return bs4.BeautifulSoup('<div class="errorName"></div>', 'html.parser') elif link.endswith('1'): return bs4.BeautifulSoup('<section class="filter"></section>', 'html.parser') elif link.endswith('2'): return bs4.BeautifulSoup('<div class="proStatus"></div>', 'html.parser') else: return False def process_link(link): """处理单个链接,返回分类标识和链接,无匹配则返回None""" req_result = manage_requests(link) if isinstance(req_result, bool): return None try: if req_result.find('div', class_="errorName"): return ('list1', link) elif req_result.find('section', class_='filter'): return ('list2', link) elif req_result.find('div', class_="proStatus"): return ('list3', link) except Exception as error: print(f"处理链接{link}出错: {error}") return None def main(): # 主进程一次性读取数据库,避免多进程重复读取 main_list = get_data_from_db() empty_list_1 = [] empty_list_2 = [] empty_list_3 = [] # 创建进程池,默认使用CPU核心数 with Pool(processes=os.cpu_count()) as pool: # 批量处理链接,imap_unordered返回处理完成的结果(顺序不固定) for result in pool.imap_unordered(process_link, main_list): if not result: continue category, link = result if category == 'list1': empty_list_1.append(link) elif category == 'list2': empty_list_2.append(link) elif category == 'list3': empty_list_3.append(link) # 结果示例输出 print(f"list1数量: {len(empty_list_1)}") print(f"list2数量: {len(empty_list_2)}") print(f"list3数量: {len(empty_list_3)}") if __name__ == "__main__": main()
关键改进点
- 避免重复读取数据库:主进程一次性获取
main_list,再分发给子进程 - 自动任务分配:通过
Pool.imap_unordered实现任务的高效分配,无需手动拆分列表 - 安全结果收集:子进程返回分类结果,主进程统一处理,解决进程间内存隔离问题
- 容错性提升:单个链接处理出错不影响整体任务,且会打印错误信息
内容的提问来源于stack exchange,提问作者OmidJr
相关产品推荐
相关产品推荐

