python中进程池和回调函数
一、数据共享
1.进程间的通信应该尽量避免共享数据的方式
2.进程间的数据是独立的,可以借助队列或管道实现通信,二者都是基于消息传递的。
虽然进程间数据独立,但可以用过Manager实现数据共享,事实上Manager的功能远不止于此。
|
1
2
3
4
|
命令就是一个程序,按回车就会执行(这个只是在windows情况下)tasklist 查看进程tasklist | findstr pycharm #(findstr是进行过滤的),|就是管道(tasklist执行的内容就放到管道里面了,管道后面的findstr pycharm就接收了) |
3.(IPC)进程之间的通信有两种实现方式:管道和队列
from multiprocessing import Manager,Process,Lock
2 def work(dic,mutex):
3 # mutex.acquire()
4 # dic['count']-=1
5 # mutex.release()
6 # 也可以这样加锁
7 with mutex:
8 dic['count'] -= 1
9 if __name__ == '__main__':
10 mutex = Lock()
11 m = Manager() #实现共享,由于字典是共享的字典,所以得加个锁
12 share_dic = m.dict({'count':100})
13 p_l = []
14 for i in range(100):
15 p = Process(target=work,args=(share_dic,mutex))
16 p_l.append(p) #先添加进去
17 p.start()
18 for i in p_l:
19 i.join()
20 print(share_dic)
21 # 共享就意味着会有竞争,
二、进程池
在利用Python进行系统管理的时候,特别是同时操作多个文件目录,或者远程控制多台主机,并行操作可以节约大量的时间。多进程是实现并发的手段之一,需要注意的问题是:
- 很明显需要并发执行的任务通常要远大于核数
- 一个操作系统不可能无限开启进程,通常有几个核就开几个进程
- 进程开启过多,效率反而会下降(开启进程是需要占用系统资源的,而且开启多余核数目的进程也无法做到并行)
例如当被操作对象数目不大时,可以直接利用multiprocessing中的Process动态成生多个进程,十几个还好,但如果是上百个,上千个。。。手动的去限制进程数量却又太过繁琐,此时可以发挥进程池的功效。
那么什么是进程池呢?进程池就是控制进程数目
ps:对于远程过程调用的高级应用程序而言,应该使用进程池,Pool可以提供指定数量的进程,供用户调用,当有新的请求提交到pool中时,如果池还没有满,那么就会创建一个新的进程用来执行该请求;但如果池中的进程数已经达到规定最大值,那么该请求就会等待,直到池中有进程结束,就重用进程池中的进程。
进程池的结构:
创建进程池的类:如果指定numprocess为3,则进程池会从无到有创建三个进程,然后自始至终使用这三个进程去执行所有任务,不会开启其他进程
1.创建进程池
|
1
|
Pool([numprocess [,initializer [, initargs]]]):创建进程池 |
2.参数介绍
|
1
2
3
|
numprocess:要创建的进程数,如果省略,将默认为cpu_count()的值,可os.cpu_count()查看initializer:是每个工作进程启动时要执行的可调用对象,默认为Noneinitargs:是要传给initializer的参数组 |
3.方法介绍
|
1
2
3
4
5
6
7
8
9
10
11
12
13
|
p.apply(func [, args [, kwargs]]):在一个池工作进程中执行func(*args,**kwargs),然后返回结果。需要强调的是:此操作并不会在所有池工作进程中并执行func函数。如果要通过不同参数并发地执行func函数,必须从不同线程调用p.apply()函数或者使用p.apply_async()p.apply_async(func [, args [, kwargs]]):在一个池工作进程中执行func(*args,**kwargs),然后返回结果。此方法的结果是AsyncResult类的实例,callback是可调用对象,接收输入参数。当func的结果变为可用时,将理解传递给callback。callback禁止执行任何阻塞操作,否则将接收其他异步操作中的结果。 p.close():关闭进程池,防止进一步操作。禁止往进程池内在添加任务(需要注意的是一定要写在close()的上方) |
|
1
|
P.jion():等待所有工作进程退出。此方法只能在close()或teminate()之后调用 |
应用1:
from multiprocessing import Pool
2 import os,time
3 def task(n):
4 print('[%s] is running'%os.getpid())
5 time.sleep(2)
6 print('[%s] is done'%os.getpid())
7 return n**2
8 if __name__ == '__main__':
9 # print(os.cpu_count()) #查看cpu个数
10 p = Pool(4) #最大四个进程
11 for i in range(1,7):#开7个任务
12 res = p.apply(task,args=(i,)) #同步的,等着一个运行完才执行另一个
13 print('本次任务的结束:%s'%res)
14 p.close()#禁止往进程池内在添加任务
15 p.join() #在等进程池
16 print('主')
# ----------------
2 # 那么我们为什么要用进程池呢?这是因为进程池使用来控制进程数目的,
3 # 我们需要几个就开几个进程。如果不用进程池实现并发的话,会开很多的进程
4 # 如果你开的进程特别多,那么你的机器就会很卡,所以我们把进程控制好,用几个就
5 # 开几个,也不会太占用内存
6 from multiprocessing import Pool
7 import os,time
8 def walk(n):
9 print('task[%s] running...'%os.getpid())
10 time.sleep(3)
11 return n**2
12 if __name__ == '__main__':
13 p = Pool(4)
14 res_obj_l = []
15 for i in range(10):
16 res = p.apply_async(walk,args=(i,))
17 # print(res) #打印出来的是对象
18 res_obj_l.append(res) #那么现在拿到的是一个列表,怎么得到值呢?我们用个.get方法
19 p.close() #禁止往进程池里添加任务
20 p.join()
21 # print(res_obj_l)
22 print([obj.get() for obj in res_obj_l]) #这样就得到了
那么什么是同步,什么是异步呢?
同步就是指一个进程在执行某个请求的时候,若该请求需要一段时间才能返回信息,那么这个进程将会一直等待下去,直到收到返回信息才继续执行下去
异步是指进程不需要一直等下去,而是继续执行下面的操作,不管其他进程的状态。当有消息返回时系统会通知进程进行处理,这样可以提高执行的效率。
什么是串行,什么是并行呢?
举例:能并排开几辆车的就可以说是“并行”,只能一辆一辆开的就属于“串行”了。很明显,并行的速度要比串行的快得多。(并行互不影响,串行的等着一个完了才能接着另一个)
应用2:
使用进程池维护固定数目的进程(以前客户端和服务端的改进)
from socket import *
2 from multiprocessing import Pool
3 s = socket(AF_INET,SOCK_STREAM)
4 s.setsockopt(SOL_SOCKET,SO_REUSEADDR,1) #端口重用
5 s.bind(('127.0.0.1',8081))
6 s.listen(5)
7 print('start running...')
8 def talk(coon,addr):
9 while True: # 通信循环
10 try:
11 cmd = coon.recv(1024)
12 print(cmd.decode('utf-8'))
13 if not cmd: break
14 coon.send(cmd.upper())
15 print('发送的是%s'%cmd.upper().decode('utf-8'))
16 except Exception:
17 break
18 coon.close()
19 if __name__ == '__main__':
20 p = Pool(4)
21 while True:#链接循环
22 coon,addr = s.accept()
23 print(coon,addr)
24 p.apply_async(talk,args=(coon,addr))
25 s.close()
26 #因为是循环,所以就不用p.join了
from socket import *
2 c = socket(AF_INET,SOCK_STREAM)
3 c.connect(('127.0.0.1',8081))
4 while True:
5 cmd = input('>>:').strip()
6 if not cmd:continue
7 c.send(cmd.encode('utf-8'))
8 data = c.recv(1024)
9 print('接受的是%s'%data.decode('utf-8'))
10 c.close()
三、回调函数
|
1
2
3
4
5
6
7
|
回调函数什么时候用?(回调函数在爬虫中最常用)造数据的非常耗时处理数据的时候不耗时你下载的地址如果完成了,就自动提醒让主进程解析谁要是好了就通知解析函数去解析(回调函数的强大之处) |
需要回调函数的场景:进程池中任何一个任务一旦处理完了,就立即告知主进程:我好了额,你可以处理我的结果了。主进程则调用一个函数去处理该结果,该函数即回调函数
我们可以把耗时间(阻塞)的任务放到进程池中,然后指定回调函数(主进程负责执行),这样主进程在执行回调函数时就省去了I/O的过程,直接拿到的是任务的结果。
from multiprocessing import Pool
2 import requests
3 import os
4 import time
5 def get_page(url):
6 print('<%s> is getting [%s]' %(os.getpid(),url))
7 response = requests.get(url) #得到地址
8 time.sleep(2)
9 print('<%s> is done [%s]'%(os.getpid(),url))
10 return {'url':url,'text':response.text}
11 def parse_page(res):
12 '''解析函数'''
13 print('<%s> parse [%s]'%(os.getpid(),res['url']))
14 with open('db.txt','a') as f:
15 parse_res = 'url:%s size:%s\n' %(res['url'],len(res['text']))
16 f.write(parse_res)
17 if __name__ == '__main__':
18 p = Pool(4)
19 urls = [
20 'https://www.baidu.com',
21 'http://www.openstack.org',
22 'https://www.python.org',
23 'https://help.github.com/',
24 'http://www.sina.com.cn/'
25 ]
26 for url in urls:
27 obj = p.apply_async(get_page,args=(url,),callback=parse_page)
28 p.close()
29 p.join()
30 print('主',os.getpid()) #都不用.get()方法了
如果在主进程中等待进程池中所有任务都执行完毕后,再统一处理结果,则无需回调函数
from multiprocessing import Pool
2 import requests
3 import os
4 def get_page(url):
5 print('<%os> get [%s]' %(os.getpid(),url))
6 response = requests.get(url) #得到地址 response响应
7 return {'url':url,'text':response.text}
8 if __name__ == '__main__':
9 p = Pool(4)
10 urls = [
11 'https://www.baidu.com',
12 'http://www.openstack.org',
13 'https://www.python.org',
14 'https://help.github.com/',
15 'http://www.sina.com.cn/'
16 ]
17 obj_l= []
18 for url in urls:
19 obj = p.apply_async(get_page,args=(url,))
20 obj_l.append(obj)
21 p.close()
22 p.join()
23 print([obj.get() for obj in obj_l])
python中进程池和回调函数的更多相关文章
- Python 3 并发编程多进程之进程池与回调函数
Python 3 进程池与回调函数 一.进程池 在利用Python进行系统管理的时候,特别是同时操作多个文件目录,或者远程控制多台主机,并行操作可以节约大量的时间.多进程是实现并发的手段之一,需要注意 ...
- python语法基础-并发编程-进程-进程池以及回调函数
############### 进程池 ############## """ 进程池的概念 为什么会有进程池? 1,因为每次开启一个进程,都需要创建一个内存空间 ...
- python并发编程之多进程2-------------数据共享及进程池和回调函数
一.数据共享 1.进程间的通信应该尽量避免共享数据的方式 2.进程间的数据是独立的,可以借助队列或管道实现通信,二者都是基于消息传递的. 虽然进程间数据独立,但可以用过Manager实现数据共享,事实 ...
- python并发编程之多进程2-(数据共享及进程池和回调函数)
一.数据共享 1.进程间的通信应该尽量避免共享数据的方式 2.进程间的数据是独立的,可以借助队列或管道实现通信,二者都是基于消息传递的. 虽然进程间数据独立,但可以用过Manager实现数据共享,事实 ...
- python并发编程之多进程2数据共享及进程池和回调函数
一.数据共享 尽量避免共享数据的方式 可以借助队列或管道实现通信,二者都是基于消息传递的. 虽然进程间数据独立,但可以用过Manager实现数据共享,事实上Manager的功能远不止于此. 命令就是一 ...
- Python之网路编程之进程池及回调函数
一.数据共享 1.进程间的通信应该尽量避免共享数据的方式 2.进程间的数据是独立的,可以借助队列或管道实现通信,二者都是基于消息传递的. 虽然进程间数据独立,但可以用过Manager实现数据共享,事实 ...
- Python 进程池的回调函数
import os from multiprocessing import Pool,Process def f1(n): print('进程池里面的进程id',os.getpid()) print( ...
- 进程池与回调函数与正则表达式和re爬虫例子
# 使用进程池的进程爬取网页内容,使用回调函数处理数据,用到了正则表达式和re模块 import re from urllib.request import urlopen from multipro ...
- python中进程池的应用
#原创,转载请联系 假设我们写的一个程序需要运行100个子进程的时候,那么写程序时,不可能循环创建销毁100个进程吧?进程的创建与销毁是很耗系统的资源的. 进程池的作用就体现出来了. 进程池可以控制进 ...
随机推荐
- vue v-model 的使用
Vue的核心特性之一是双向绑定,vue的响应式原理是实现了数据->视图 v-bind只能实现数据的单向绑定 ,从M自动绑定到V 使用v-model 可以实现表单元素的双向绑定,且只能应用到表单元 ...
- Uedit32_17.00 修改某一语言背景色-修改后续名后语法着色及某语言的大括号{}对齐
修改UE的背景色:高级-配置-编辑器显示-其它-设置颜色 新增扩展名语法着色:如以tpl为后缀的html代码格式着色高级-配置-编辑器显示-语法着色-语言选言[选中要着色的语言html]-打开-在'F ...
- 使用BaGet来管理内部Nuget包
有的时候,我们想要制作一些nuget包,供自己内部调用,不想公开出去,那么就需要一个能够集中管理nuget包的服务了,今天我来给大家介绍一款轻便好用的包管理服务-----BaGet 下载并部署BaGe ...
- 04机器学习实战之朴素贝叶斯scikit-learn实现
In [8]: import numpy as np import matplotlib.pyplot as plt import matplotlib as mpl from sklearn.pre ...
- Linux–Nginx攻略
什么是Nginx Nginx (“engine x”) 是一个高性能的HTTP和反向代理服务器,也是一个IMAP/POP3/SMTP服务器.Nginx是由Igor Sysoev为俄罗斯访问量第二的Ra ...
- 狼人杀校园升级版:学霸大战学渣 Who is the king of examination!
之前在微博上看到一个很老的段子 写道 天黑请闭眼.学霸请睁眼,学霸请答题,好的学霸请闭眼:学渣请睁眼,学渣请坐弊,好的学渣请闭眼:监考老师请睁眼,监考老师请确定坐弊考生,监考老师请统一意见,好的监考老 ...
- Photoshop画笔工具的使用
现在我们按下[B]从工具栏选择画笔工具,如果选中了铅笔就[SHIFT B]切换到画笔.然后按下[D],它的作用是将颜色设置为默认的前景黑色.背景白色.也可以点击工具栏颜色区的默认按钮(下左图红色箭头处 ...
- Nginx实现反向代理与负载均衡
1.什么是反向代理 使用nginx实现反向代理,Nginx只做请求的转发,后台有多个http服务器提供服务,nginx的功能就是把请求转发给后面的服务器,决定把请求转发给谁. 2.在一个虚拟机上创建两 ...
- php array_intersect()函数 语法
php array_intersect()函数 语法 作用:用于比较两个(或更多个)数组的键值,并返回交集.直线电机生产厂家 语法:array_intersect(array1,array2,arra ...
- 怎么测试php代码
没有任何一名程序员可以一气呵成.完美无缺的在不用调试的情况下完成一个功能或模块.调试实际分很多种情况. 暴力调试 这种方式简单粗暴,一般PHP程序员都会用,那就是浏览器调试,在编辑器内写完代码后随后打 ...