我需要从存储在.txt文件中的域(大约50 MB大小)进行大量网页编写。
我想做多线程。因此,我将一些条目加载到Python列表中,并使用线程处理每个条目。
示例:
biglist = ['google.com','facebook.com','apple.com']
threads = [threading.Thread(target=fetch_url, args=(chuck,))
for domain in biglist]
for thread in threads:
thread.start()
for thread in threads:
thread.join()
它可以工作,但在我看来,它不是很有效,因为有大量的内存使用,而且需要很长时间才能完成。
有什么更好的方法来实现我的目标?
答案 0 :(得分:0)
您使用的是错误的库。 threading.Thread
并没有真正受益于多个处理器,因为它被Global Interpreter Lock阻止。
来自threading
模块(c.f.)的文档:
CPython实现细节:在CPython中,由于全局解释器锁,只有一个线程可以同时执行Python代码(即使某些面向性能的库可能会克服这个限制)。如果您希望应用程序更好地利用多核计算机的计算资源,建议您使用
multiprocessing
。但是,如果要同时运行多个I / O绑定任务,threading
仍然是一个合适的模型。
我建议您使用process pool模块中的multiprocessing
和map()
来并行计算结果。使用比处理器更多的进程没有任何意义。
来自multiprocessing
模块(c.f.)的文档:
multiprocessing
是一个使用类似于threading
模块的API支持产生进程的包。multiprocessing
包提供本地和远程并发,通过使用子进程而不是线程有效地侧面执行全局解释器锁。因此,multiprocessing
模块允许程序员充分利用给定计算机上的多个处理器。它可以在Unix和Windows上运行。
示例:
from multiprocessing import Pool
number_of_processors = 3
data = range(10)
def func(x):
print "processing", x
return x*x
pool = Pool(number_of_processors)
ret = pool.map(func, data)
输出结果为:
$ python test.py
processing 0
processing 1
processing 3
processing 2
processing 4
processing 5
processing 6
processing 7
processing 8
processing 9
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
答案 1 :(得分:0)
不要使用列表/线程,而是使用队列/进程 如果你知道Redis我建议RQ(http://python-rq.org) - 我做同样的事情并且工作得非常好。
答案 2 :(得分:0)
添加到moooeeeeps的答案。 还有另一种在一个线程中处理大量连接的方法,而不会产生昂贵的进程。 Gevent与多处理/多线程有类似的api。
文档和教程:
还有一个用于抓取网址的python框架: http://scrapy.org/
来自docs asyc / sync抓取网址的示例: import gevent.monkey gevent.monkey.patch_socket()
import gevent
import urllib2
import simplejson as json
def fetch(pid):
response = urllib2.urlopen('http://json-time.appspot.com/time.json')
result = response.read()
json_result = json.loads(result)
datetime = json_result['datetime']
print('Process %s: %s' % (pid, datetime))
return json_result['datetime']
def synchronous():
for i in range(1,10):
fetch(i)
def asynchronous():
threads = []
for i in range(1,10):
threads.append(gevent.spawn(fetch, i))
gevent.joinall(threads)
print('Synchronous:')
synchronous()
print('Asynchronous:')
asynchronous()