You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python多线程邮件验证列表不同步问题求助

多线程邮件验证结果错位问题解决

你的推测完全正确——多线程环境下任务完成顺序不固定,先结束的线程会先把结果追加到列表,导致emails_list、deliverable_list、hostexists_list的索引无法一一对应,最终Excel里的结果和邮箱错位。

原代码的核心问题是将邮箱与验证结果分开存储,依赖线程执行顺序保证索引同步,这在多线程场景下根本不可靠。下面给出两种可行的修正方案:


方案一:使用ThreadPoolExecutor(推荐,代码更简洁可控)

concurrent.futures.ThreadPoolExecutor可以直接获取每个任务的返回值,我们可以让每个任务返回绑定了邮箱的结果字典,最后统一整理成DataFrame:

import pandas as pd
import csv
from email_verifier import Verifier
from concurrent.futures import ThreadPoolExecutor, as_completed

csvFilename = r'test2.csv'
emails_list = []

# 读取邮箱列表
with open(csvFilename, 'r', encoding="utf-8") as csvFile:
    csvreader = csv.reader(csvFile)
    next(csvreader)  # 跳过表头行
    for row in csvreader:
        _, email = [str(val) for val in row]
        emails_list.append(email)

def verify_email(email):
    try:
        verifier = Verifier(source_addr='example@gmail.com')
        result = verifier.verify(email)
        return {
            'Email': email,
            'Deliverable': result["deliverable"],
            'Host exists': result["host_exists"]
        }
    except Exception as e:
        # 异常时返回默认值,避免结果缺失
        print(f"验证邮箱 {email} 失败: {str(e)}")
        return {
            'Email': email,
            'Deliverable': False,
            'Host exists': False
        }

# 配置并发线程数
max_workers = 5
results = []

with ThreadPoolExecutor(max_workers=max_workers) as executor:
    # 提交所有验证任务
    future_map = {executor.submit(verify_email, email): email for email in emails_list}
    # 遍历完成的任务,收集结果
    for future in as_completed(future_map):
        results.append(future.result())

# 转换为DataFrame,可选:保持原邮箱顺序
df = pd.DataFrame(results)
df = df.set_index('Email').reindex(emails_list).reset_index()

# 保存到Excel
df.to_excel('gmail_multi_thread_1.xlsx', index=False)

方案二:基于原生threading模块修改(兼容原代码结构)

如果不想更换线程管理方式,可以通过线程锁保证结果列表的原子操作,同时将邮箱与验证结果绑定成元组存储:

import threading
import time
import pandas as pd
import csv
from email_verifier import Verifier

maxthreads = 5
pool_sema = threading.Semaphore(value=maxthreads)
results_list = []  # 存储格式:(Email, Deliverable, Host exists)
lock = threading.Lock()  # 线程锁,防止多线程同时写入列表

csvFilename = r'test2.csv'
emails_list = []

with open(csvFilename, 'r', encoding="utf-8") as csvFile:
    csvreader = csv.reader(csvFile)
    next(csvreader)  # 跳过表头
    for row in csvreader:
        _, email = [str(val) for val in row]
        emails_list.append(email)

def task(email):
    pool_sema.acquire()
    try:
        verifier = Verifier(source_addr='example@gmail.com')
        result = verifier.verify(email)
        # 加锁后写入结果,保证线程安全
        with lock:
            results_list.append((
                email,
                result["deliverable"],
                result["host_exists"]
            ))
        time.sleep(3)
    except Exception as e:
        print(f"验证邮箱 {email} 失败: {str(e)}")
        with lock:
            results_list.append((email, False, False))
    finally:
        pool_sema.release()

def create_threads():
    threads = [threading.Thread(target=task, args=(email,)) for email in emails_list]
    for t in threads:
        t.start()
    for t in threads:
        t.join()

create_threads()

# 转换为DataFrame,可选:保持原邮箱顺序
df = pd.DataFrame(results_list, columns=['Email', 'Deliverable', 'Host exists'])
df = df.set_index('Email').reindex(emails_list).reset_index()

df.to_excel('gmail_multi_thread_1.xlsx', index=False)

关键改进点

  1. 绑定邮箱与结果:不再分开存储三个独立列表,将每个邮箱和对应的验证结果作为一个整体存储,从根源上避免索引错位。
  2. 线程安全操作:方案二中通过threading.Lock保证对结果列表的修改是原子操作,防止多线程同时写入导致的数据混乱。
  3. 可选顺序保持:通过reindex方法可以让最终Excel表格保持原邮箱列表的顺序,不受线程完成顺序影响。

内容的提问来源于stack exchange,提问作者SAHU

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.22 06:36:19