Python这门语言在设计的时候,有一个全局解释器锁(Global Interpreter Lock, GIL)
。
这导致Python的多线程都是伪多线程,即本质上还是一个线程
,但是这个线程每个事情只做几毫秒,几毫秒以后就保存现场,换做其他事情,几毫秒后再做其他事情,一轮之后回到第一件事上,恢复现场再做几毫秒,继续换……微观上的单线程
,在宏观上就像同时在做几件事。
这种机制在I/O(Input/Output,输入/输出)密集型的操作上影响不大,但是在CPU计算密集型的操作上面,由于只能使用CPU的一个核,就会对性能产生非常大的影响。所以涉及计算密集型的程序,就需要使用多进程,Python的多进程不受GIL的影响。
爬虫属于I/O密集型的程序,所以使用多线程可以大大提高爬取效率。
多进程库
multiprocessing
本身是Python的多进程库,用来处理与多进程相关的操作。
但是由于进程与进程之间不能直接共享内存和堆栈资源,而且启动新的进程开销也比线程大得多,因此使用多线程来爬取比使用多进程有更多的优势。
multiprocessing
下面有一个dummy
模块,它可以让Python的线程使用multiprocessing
的各种方法。
dummy
下面有一个Pool
类,它用来实现线程池。
这个线程池有一个map()
方法,可以让线程池里面的所有线程都“同时”执行一个函数。
1 | from multiprocessing.dummy import Pool |
程池的map()
方法接收两个参数,第1个参数是函数名,第2个参数是一个列表。
第1个参数仅仅是函数的名字,是不能带括号的。
第2个参数是一个可迭代的对象,这个可迭代对象里面的每一个元素都会被函数clac_power2()
接收来作为参数。除了列表以外,元组、集合或者字典都可以作为map()
的第2个参数。