multiprocessing
模块就是跨平台版本的多进程模块,它提供了一个Process类来代表一个进程对象,这个对象可以理解为是一个独立的进程,可以执行另外的事情。
多进程的创建
多进程的创建和多线程的创建差不多
import multiprocessing
from time import sleep
def dog():
for i in range(5):
print('www%d'%i)
sleep(1.5)
def cat():
for i in range(5):
print('mmm%d'%i)
sleep(1)
if __name__ == '__main__':
t1 = multiprocessing.Process(target=dog)
t2 = multiprocessing.Process(target=cat)
t1.start()
t2.start()
只是把threading.Thread
换成multiprocessing.Process
进程与线程的区别
- 线程执行开销小,但不利于资源的管理和保护;而进程相反
- 线程不能够独立执行,必须依存在进程中
- 线程的划分尺度小于进程(资源比进程少),使得多线程程序的并发性较高
- 进程在执行过程中拥有独立的内存单元,而多线程共享内存,从而极大的提高了程序的运行效率
进程间通信
- 可以使用socket通信来进行进程间通信
通过写文件和读文件来进行进程间通信
3. 通过队列(Queue)来进行进程间通信(重点)
队列的特点是先进先出,这样我们就可以在一个进程中往队列中写东西,另一个进程从队列中读取数据,这样就实现了进程通信。
import multiprocessing
from queue import Empty
from time import sleep
def download(q):
# 模拟下载数据
for i in range(10):
q.put(i)
sleep(1)
def analysis(q):
# 模拟分析数据
analysis_data = list()
while True:
try:
data = q.get(timeout=2)
except Empty:
break
analysis_data.append(data)
print(analysis_data)
def main():
q = multiprocessing.Queue()
p1 = multiprocessing.Process(target=download, args=(q,))
p2 = multiprocessing.Process(target=analysis, args=(q,))
p1.start()
p2.start()
if __name__ == '__main__':
main()
这里的案例一个进程模拟下载数据,一个进程模拟分析数据,用队列进行通信
进程池
如果要创建子程序很多时,就可以考虑创建一个进程池
初始化进程池Pool
时,可以指定一个最大进程数,当有新的请求提交到Pool时,如果还没有满,那么就会创建一个新的进程来执行请求,如果Pool中满了,那么该请求就会等待,直到池中有进程结束,才会用之前的进程来执行新的任务。
- 在进程池中如果代码出现异常不会报错
例如我之前写的爬虫改进版:
def main():
q = multiprocessing.Manager().Queue() # 创建进程池内Queue消息队列通信
p = multiprocessing.Process(target=insert_data,args=(q,))
p.start()
po = multiprocessing.Pool(3)
for i in range(1,11):
po.apply_async(jd_spider,(q,i))
po.close()
po.join()
这里有一个坑,在进程池中进行队列通信是定义队列要用multiprocessing.Manager().Queue()
1 条评论
博客很棒 欢迎回访我哦