使用Map与Partial后for循环仅执行首行的问题排查与修复
问题描述
使用partial绑定参数结合ThreadPoolExecutor处理IO密集型任务时,get_the_text函数内的for循环仅执行首行就跳过其余行,无法遍历所有链接发送请求。
相关代码
线程池调用代码
get_the_text_par = partial(get_the_text,_link_column=link,_firms=firms) with ThreadPoolExecutor() as executor: chunk_size= len(results) if len(results)<10 else len(results) // 10 chunks=[results.iloc[i:i + chunk_size] for i in range(0, len(results),chunk_size)] result = list(executor.map(get_the_text_par,chunks))
get_the_text函数实现
def get_the_text(_df,_firms:list,_link_column:str): ''' 发送请求获取文章文本 参数 ---------- _df : DataFrame 返回 ------- 包含文章文本的DataFrame ''' _df.reset_index(inplace=True) print(_df) for k,link in enumerate(_df[[f'{_link_column}']]): print(k,'\n',_df.loc[k,f'{_link_column}']) if link: website_text=list() try: page_status_code,page_content,page_url = send_two_requests(_df.loc[k,f'{_link_column}']) # 省略后续处理逻辑 ...
测试数据
data = { 'index': [1366, 4767, 6140, 11898], 'DATE': ['2014-01-12', '2014-01-12', '2014-01-12', '2014-01-12'], 'SOURCES': ['go.com', 'bloomberg.com', 'latimes.com', 'usatoday.com'], 'SOURCEURLS': [ 'http://abcnews.go.com/Business/wireStory/mercedes-recalls-372k-suvs-21445846', 'http://www.bloomberg.com/news/2014-01-12/vw-patent-application-shows-in-car-gas-heater.html', 'http://www.latimes.com/business/autos/la-fi-hy-autos-recall-mercedes-20140112-story.html', 'http://www.usatoday.com/story/money/cars/2014/01/12/mercedes-recall/4437279/' ], 'Tone': [-0.375235, -1.842752, 1.551724, 2.521008], 'Positive_Score': [2.626642, 1.228501, 3.275862, 3.361345], 'Negative_Score': [3.001876, 3.071253, 1.724138, 0.840336], 'Polarity': [5.628518, 4.299754, 5.0, 4.201681], 'Activity_Reference_Density': [22.326454, 18.918919, 22.931034, 19.327731], 'Self_Group_Reference_Density': [0.0, 0.0, 0.344828, 0.840336], 'Year': [2014, 2014, 2014, 2014], 'Month': [1, 1, 1, 1], 'Day': [12, 12, 12, 12], 'Hour': [0, 0, 0, 0], 'Minute': [0, 0, 0, 0], 'Second': [0, 0, 0, 0], 'Mentioned_firms': ['mercedes', 'vw', 'mercedes', 'mercedes'], 'text': ['', '', '', ''] } # 创建DataFrame df = pd.DataFrame(data)
问题根源与修复方案
核心问题
- 遍历方式错误:
enumerate(_df[[f'{_link_column}']])遍历的是DataFrame的列名而非行数据。_df[[col]]返回的是单列DataFrame,enumerate它时只会拿到一个元素(列名),所以循环仅执行一次。 - 变量重置错误:
website_text=list()放在循环内部,每次循环都会清空列表,导致之前的结果丢失。 - 索引处理隐患:
_df.reset_index(inplace=True)修改原DataFrame索引,可能导致后续loc取值混乱。
修复步骤
1. 修正遍历逻辑
改用enumerate(_df[_link_column])直接遍历单列的行数据,或者用_df[_link_column].items()获取索引与对应链接值:
# 方式一:直接遍历单列 for k, link in enumerate(_df[_link_column]): print(k, '\n', link) if link: # 后续处理
# 方式二:获取索引和值 for idx, link in _df[_link_column].items(): print(idx, '\n', link) if link: # 后续处理
2. 调整变量作用域
将website_text=list()移到循环外部,避免每次循环重置:
def get_the_text(_df,_firms:list,_link_column:str): _df = _df.reset_index(drop=True) # 不修改原DataFrame,返回新的带重置索引的DataFrame website_text = list() # 移到循环外 print(_df) for k, link in enumerate(_df[_link_column]): print(k,'\n', link) if link: try: page_status_code,page_content,page_url = send_two_requests(link) # 省略后续处理,比如将结果加入website_text website_text.append(...) # 更新_df的text列 _df.loc[k, 'text'] = ... except Exception as e: # 异常处理 print(f"请求链接{link}失败: {e}") return _df
3. 优化索引处理
用_df = _df.reset_index(drop=True)替代inplace=True,避免修改原DataFrame的索引,减少潜在问题。
修改后的完整
get_the_text函数 def get_the_text(_df,_firms:list,_link_column:str): ''' 发送请求获取文章文本 参数 ---------- _df : DataFrame 返回 ------- 包含文章文本的DataFrame ''' # 重置索引,不修改原DataFrame _df = _df.reset_index(drop=True) print(_df) # 初始化结果列表,放在循环外 website_text = list() # 正确遍历单列的每一行 for k, link in enumerate(_df[_link_column]): print(k,'\n', link) if link: try: page_status_code,page_content,page_url = send_two_requests(link) # 这里补充你的文本提取逻辑,示例: # extracted_text = parse_page_content(page_content) # website_text.append(extracted_text) # 更新DataFrame的text列 # _df.loc[k, 'text'] = extracted_text except Exception as e: print(f"处理链接{link}出错: {str(e)}") # 可以给错误行设置默认值 _df.loc[k, 'text'] = '' return _df
内容的提问来源于stack exchange,提问作者Mostafa Bouzari
相关产品推荐
相关产品推荐

