如何修复这个多线程Python脚本?

1 投票
2 回答
605 浏览
提问于 2025-04-16 00:27

我正在写一个Python脚本,目的是读取一系列域名,查看Mcafee的Siteadvisor服务给出的评分,然后把域名和评分结果输出到一个CSV文件里。

我的脚本是基于之前的一个回答写的。它使用urllib来抓取Siteadvisor上关于特定域名的页面(我知道这不是最好的方法,但Siteadvisor没有提供其他选择)。不幸的是,它没有产生任何结果——我总是遇到这个错误:

Traceback (most recent call last):
  File "multi.py", line 55, in <module>
    main()
  File "multi.py", line 44, in main
    resolver_thread.start()
  File "/usr/lib/python2.6/threading.py", line 474, in start
    _start_new_thread(self.__bootstrap, ())
thread.error: can't start new thread

这是我的脚本:

import threading
import urllib

class Resolver(threading.Thread):
    def __init__(self, address, result_dict):
        threading.Thread.__init__(self)
        self.address = address
        self.result_dict = result_dict

    def run(self):
        try:
            content = urllib.urlopen("http://www.siteadvisor.com/sites/" + self.address).read(12000)
            search1 = content.find("didn't find any significant problems.")
            search2 = content.find('yellow')
            search3 = content.find('web reputation analysis found potential security')
            search4 = content.find("don't have the results yet.")

            if search1 != -1:
                result = "safe"
            elif search2 != -1:
                result = "caution"
            elif search3 != -1:
                result = "warning"
            elif search4 != -1:
                result = "unknown"
            else:
                result = ""

            self.result_dict[self.address] = result

        except:
            pass


def main():
    infile = open("domainslist", "r")
    intext = infile.readlines()
    threads = []
    results = {}
    for address in [address.strip() for address in intext if address.strip()]:
        resolver_thread = Resolver(address, results)
        threads.append(resolver_thread)
        resolver_thread.start()

    for thread in threads:
        thread.join()

    outfile = open('final.csv', 'w')
    outfile.write("\n".join("%s,%s" % (address, ip) for address, ip in results.iteritems()))
    outfile.close()

if __name__ == '__main__':
    main()

如果能得到任何帮助,我将非常感激。

2 个回答

1

你可能创建的线程数量有个上限,而你可能已经超过这个上限了。

建议:创建少量固定的解析器,少于10个就能让你获得大约90%的并行处理好处。然后使用Python的队列库创建一个(线程安全的)队列。让主线程把所有的域名放到队列里,然后每个解析器从队列中一次取一个域名来处理。

1

看起来你试图启动的线程太多了。

你可以检查一下 [address.strip() for address in intext if address.strip()] 这个列表里有多少个项目。我觉得这可能是问题所在。简单来说,启动新线程是有资源限制的。

解决这个问题的方法是把你的列表分成小块,比如每块20个元素,先处理这20个(用20个线程),等这些线程完成工作后,再处理下一块。这样一直进行,直到列表里的所有元素都处理完。

你还可以使用一些线程池来更好地管理线程。(我最近用过 这个实现)。

撰写回答