Python多进程编程遇RuntimeError:主函数疑似问题求助
RuntimeError问题排查与解决
错误原因
- spawn模式的模块导入特性:使用
spawn启动子进程时,每个子进程会重新导入主模块。如果主模块中存在if __name__ == '__main__':之外的代码(比如WebDriver初始化、全局变量定义),子进程启动时会重复执行这些代码,导致进程启动阶段冲突,触发该RuntimeError。 - 跨进程共享非安全对象:你的代码中
driver(WebDriver实例)和全局dict被多个子进程共享,但WebDriver本身不是进程安全的,多进程同时操作会引发异常;全局字典在多进程下是各自独立的副本,无法实现数据汇总,还会导致并发修改问题。
解决步骤
- 隔离主进程初始化逻辑:所有需要在主进程执行的初始化操作(比如全局变量定义、WebDriver相关的初始化)必须放到
if __name__ == '__main__':代码块内,避免子进程导入时重复执行。 - 子进程独立初始化WebDriver:每个子进程必须创建自己的WebDriver实例,不能复用父进程的driver。在
extract_tag_data函数内部初始化driver,退出前关闭。 - 避免全局共享数据容器:让
extract_tag_data函数返回当前进程收集到的数据,主进程汇总所有子进程的返回结果后再生成DataFrame,不要用全局字典存储。 - 确保pool操作完成后再处理数据:
pool.map()是阻塞调用,要等所有子进程执行完毕后再进行数据处理和driver关闭操作。
修正后的代码示例
数据提取函数(独立初始化driver)
from selenium import webdriver from selenium.webdriver.common.by import By from selenium.webdriver.common.keys import Keys import unidecode import pandas as pd import multiprocessing def extract_tag_data(tag): # 子进程独立初始化driver driver = webdriver.Chrome() # 根据你的浏览器类型调整 driver.get("你的目标网页URL") # 补充目标页面URL search_bar = driver.find_element(By.XPATH, "搜索框的XPATH") # 补充搜索框定位 search_bar.send_keys(tag) search_bar.send_keys(Keys.RETURN) # 每个进程维护自己的数据列表 process_data = [] for i in range(2): articles = driver.find_elements(By.XPATH, "//table[@class='table table-hover']/tbody/tr/td[2]/div[@class='media']/div[@class='media-body']/strong/a") for article in articles[:1]: article.click() # 收集单条数据 article_data = { 'tag': tag, 'article_title': unidecode.unidecode(driver.find_element(By.XPATH,'//h1[@class="title"]').text), 'abstract': unidecode.unidecode(driver.find_element(By.XPATH,'//div[@class="abstract"]/div[1]').text), 'authors': unidecode.unidecode(",".join([element.text for element in driver.find_elements(By.XPATH,'//div[@class="authors"]/span')])), 'structs': unidecode.unidecode(",".join([element.text for element in driver.find_elements(By.XPATH,'//div[@class="authors"]/div[@class="structs"]/div[@class="struct"]/a')])) } process_data.append(article_data) driver.back() # 处理翻页,注意捕获异常避免找不到元素 try: driver.find_element(By.XPATH,'//table[@class="table table-hover"]/tfoot/tr[1]/th[2]/ul/li/a/span[@class="glyphicon glyphicon-step-forward"]').click() except: break # 没有下一页时退出循环 driver.quit() # 子进程关闭自己的driver return process_data
主函数(汇总数据)
if __name__ == '__main__': tags = ["tag1", "tag2", "tag3"] # 替换为你的tags列表 with multiprocessing.get_context('spawn').Pool(3) as pool: # 收集所有子进程返回的数据 all_data = pool.map(extract_tag_data, tags) # 扁平化数据列表 flat_data = [item for sublist in all_data for item in sublist] # 生成DataFrame并保存 df = pd.DataFrame(flat_data, columns=['article_title', 'authors', 'abstract', 'structs', 'tag']) df.to_excel(r"C:\Users\dell\Desktop\data collection\myDataset.xlsx", sheet_name='Sheet1')
内容的提问来源于stack exchange,提问作者abdo berg
相关产品推荐
相关产品推荐

