你问错了问题
看了validate_email包之后,您真正的问题是没有有效地成批处理结果。您应该只对每个域执行一次MX查找,然后只连接到每个MX服务器一次,完成握手,然后在一个批中检查该服务器的所有地址。谢天谢地,validate_email包为您完成了MX结果缓存,但是您仍然需要按服务器对电子邮件地址进行分组,以便将查询批处理到服务器本身。在
您需要编辑validate_email包来实现批处理,然后可能使用实际的threading库而不是multiprocessing向每个域提供一个线程。在
如果你的程序很慢的话,一定要对它进行分析,找出它实际花在了什么地方,而不是盲目地应用优化技巧。在
要求的解决方案
如果您正在使用缓冲IO,并且您的用例适合操作系统缓冲,那么IO已经是异步的。唯一可能获得一些优势的地方是read ahead,但是Python已经做到了,如果您使用迭代器访问一个文件(您正在这样做)。对于移动大量数据并禁用操作系统缓冲区以防止复制数据两次的程序来说,AsyncIO是一个优势。在
你需要对你的程序进行实际的评测/基准测试,看看它是否还有改进的余地。如果您的磁盘还没有达到吞吐量限制,那么就有机会通过并行执行每个电子邮件(地址?)的处理来提高性能。检查这一点最简单的方法可能是检查运行程序的内核是否已达到最大限度(即,您受CPU限制而不是IO限制)。在
如果你是CPU限制,那么你需要看看线程。不幸的是,Python线程不能并行工作,除非您有非Python的工作要做,否则您将不得不使用multiprocessing(我假设{}是一个Python函数)。在
具体如何进行取决于程序中的瓶颈在哪里,以及达到IO限制点所需的速度(因为实际速度不能超过这个速度,所以在达到该点时可以停止优化)。在
{7}你最好把它放在一个线程里,这样你就很难把它锁起来了。看看multiprocessing库,最容易使用的机制可能是Process Pools。在
使用此方法,您需要将文件iterable包装在一个^{}中,该文件将丢弃重复项,然后将其输入到^{}中,然后迭代该结果并写入两个输出文件中。在
比如:with open(email_path) as f:
for result in Pool().imap_unordered(validate_map,
itertools.ifilter(unique, f):
(good, email) = result
if good:
good_emails.write(email)
else:
bad_emails.write(email)
validate_map函数应该很简单,例如:
^{pr2}$
unique函数应该类似于:seen_emails = set()
def unique(e):
if e in seen_emails:
return False
seen_emails.add(e)
return True
ETA:我刚刚意识到validate_email是一个实际联系SMTP服务器的库。考虑到Python代码不忙,您可以使用线程。尽管threadingAPI不如多处理库方便,但是您可以使用multiprocessing.dummy来拥有基于线程的池。在
如果你是CPU受限的,那么拥有比内核更多的线程/进程是不值得的,但是由于你的瓶颈是网络IO,你可以从更多的线程/进程中获益。由于进程很昂贵,您需要交换到线程,然后提高并行运行的数量(尽管您应该礼貌地避免DOS攻击您所连接的服务器)。在
考虑from multiprocessing.dummy import Pool as ThreadPool,然后调用ThreadPool(processes=32).imap_unordered()。在