设为首页 收藏本站
查看: 1144|回复: 0

[经验分享] Python 学习笔记 - 多进程和进程池

[复制链接]

尚未签到

发表于 2018-8-16 11:16:22 | 显示全部楼层 |阅读模式
  前面学习了多线程,接下来学习多进程的创建和使用。多进程更适合计算密集型的操作,他的语法和多线程非常相像,唯一需要注意的是,多线程之间是可以直接共享内存数据的;但是多进程默认每个进程是不能访问其他进程(程序)的内容。我们可以通过一些特殊的方式(队列,数组和字典)来实现,注意这几个数据结构和平常使用的不太一样,是在多进程中特殊定义的。
  例如:通过queue来共享数据
#!/usr/bin/env python  
# -*- coding:utf-8 -*-
  
# Author:Alex Li
  
from multiprocessing import Process
  
from multiprocessing import queues
  
import multiprocessing
  
from multiprocessing import Array
  
def foo(i,arg):
  
    arg.put(i)
  
    print('say hi',i,arg.qsize())
  
if __name__ == "__main__":
  
    # li = []
  
    li = queues.Queue(20,ctx=multiprocessing)
  
    for i in range(10):
  
        p = Process(target=foo,args=(i,li,))
  
        p.start()
  
        p.join()
  
------------------
  
say hi 0 1
  
say hi 1 2
  
say hi 2 3
  
say hi 3 4
  
say hi 4 5
  
say hi 5 6
  
say hi 6 7
  
say hi 7 8
  
say hi 8 9
  
say hi 9 10
  例2 通过array来共享数据,注意array初始化的时候就需要固定数据类型和长度
from multiprocessing import Process  
from multiprocessing import queues
  
import multiprocessing
  
from multiprocessing import Array
  
def foo(i,arg):
  
    arg = i + 100
  
    for item in arg:
  
        print(item)
  
    print('================')
  
if __name__ == "__main__":
  

  
    li = Array('i', 10)
  
    for i in range(10):
  
        p = Process(target=foo,args=(i,li,))
  
        p.start()
  
----------------
  
0
  
0
  
0
  
0
  
0
  
0
  
0
  
107
  
0
  
0
  
================
  
0
  
0
  
0
  
0
  
0
  
0
  
0
  
107
  
108
  
0
  
================
  
0
  
101
  
0
  
0
  
0
  
0
  
0
  
107
  
108
  
0
  
================
  
0
  
101
  
0
  
0
  
0
  
0
  
106
  
107
  
108
  
0
  
================
  
0
  
101
  
0
  
0
  
0
  
105
  
106
  
107
  
108
  
0
  
================
  
...(等等省略)
  例3 通过字典方式进程间共享
#!/usr/bin/env python  
# -*- coding:utf-8 -*-
  
# Author:Alex Li
  
from multiprocessing import Process
  
from multiprocessing import queues
  
import multiprocessing
  
from multiprocessing import Manager
  
def foo(i,arg):
  

  
    arg = i + 100
  
    print(arg.values())
  
if __name__ == "__main__":
  
    # li = []
  
    # li = queues.Queue(20,ctx=multiprocessing)
  
    obj = Manager()
  
    li = obj.dict()
  
    for i in range(10):
  
        p = Process(target=foo,args=(i,li,))
  
        p.start()
  
        p.join()
  
----------------
  
[100]
  
[100, 101]
  
[100, 101, 102]
  
[100, 101, 102, 103]
  
[100, 101, 102, 103, 104]
  
[100, 101, 102, 103, 104, 105]
  
[100, 101, 102, 103, 104, 105, 106]
  
[100, 101, 102, 103, 104, 105, 106, 107]
  
[100, 101, 102, 103, 104, 105, 106, 107, 108]
  
[100, 101, 102, 103, 104, 105, 106, 107, 108, 109]
  和线程类似,当多个进程操作同一个全局变量的时候,需要加锁,不然可能错误;
  比如
#!/usr/bin/env python  
# -*- coding:utf-8 -*-
  
# Author:Alex Li
  
from multiprocessing import Process
  
from multiprocessing import queues
  
from multiprocessing import Array
  
from multiprocessing import RLock, Lock, Event, Condition, Semaphore
  
import multiprocessing
  
import time
  
def foo(i,lis):
  
    lis[0] = lis[0] - 1
  
    time.sleep(1)
  
    print('say hi',lis[0])
  
if __name__ == "__main__":
  
    # li = []
  
    li = Array('i', 1)
  
    li[0] = 10
  
    for i in range(10):
  
        p = Process(target=foo,args=(i,li))
  
        p.start()
  
-------------
  
say hi 0
  
say hi 0
  
say hi 0
  
say hi 0
  
say hi 0
  
say hi 0
  
say hi 0
  
say hi 0
  
say hi 0
  
say hi 0
  如何修复?
  两种方式,一个是p.start()下面加个p.join(),那真的就算按顺序一个个执行了;还有一个方式就是加锁
#!/usr/bin/env python  
# -*- coding:utf-8 -*-
  
# Author:Alex Li
  
from multiprocessing import Process
  
from multiprocessing import queues
  
from multiprocessing import Array
  
from multiprocessing import RLock, Lock, Event, Condition, Semaphore
  
import multiprocessing
  
import time
  
def foo(i,lis,lc):
  
    lc.acquire()
  
    lis[0] = lis[0] - 1
  
    time.sleep(1)
  
    print('say hi',lis[0])
  
    lc.release()
  
if __name__ == "__main__":
  
    # li = []
  
    li = Array('i', 1)
  
    li[0] = 10
  
    lock = RLock()
  
    for i in range(10):
  
        p = Process(target=foo,args=(i,li,lock))
  
        p.start()
  
--------------
  
say hi 9
  
say hi 8
  
say hi 7
  
say hi 6
  
say hi 5
  
say hi 4
  
say hi 3
  
say hi 2
  
say hi 1
  
say hi 0
  和线程池相比,Python已经提供了完备的进程池模块,因此可以直接使用。进程池里面有2种方法,apply或apply_async;前者是阻塞,而后者是非阻塞的
  例如下面例子我使用的apply_async,那么所有的进程是(非阻塞)同时执行的,当执行到time.sleep(5),每个子线程会卡5秒,而同时主线程执行到了pool.terminate(),这个时候就直接终止程序了
#!/usr/bin/env python  
# -*- coding:utf-8 -*-
  

  
from multiprocessing import Pool
  
import time
  
def f1(arg):
  
    print(arg,'b')
  
    time.sleep(5)
  
    print(arg,'a')
  
if __name__ == "__main__":
  
    pool = Pool(5)
  
    for i in range(30):
  
        # pool.apply(func=f1,args=(i,))#按照顺序执行
  
        pool.apply_async(func=f1,args=(i,))#同时执行
  
    # pool.close() # 所有的任务执行完毕
  
    time.sleep(2)
  
    pool.terminate() # 立即终止
  
    pool.join()
  
    pass
  
--------------
  
"C:\Program Files\Python3\python.exe" C:/temp/s13day11/day11/s16.py
  
0 b
  
1 b
  
2 b
  
3 b
  
4 b
  如果改成close(),那么他会等待pool中的任务执行完成之后再中止程序
from multiprocessing import Pool  
import time
  
def f1(arg):
  
    print(arg,'b')
  
    time.sleep(5)
  
    print(arg,'a')
  
if __name__ == "__main__":
  
    pool = Pool(5)
  
    for i in range(30):
  
        # pool.apply(func=f1,args=(i,))#按照顺序执行
  
        pool.apply_async(func=f1,args=(i,))#同时执行
  
    pool.close() # 所有的任务执行完毕
  
    time.sleep(2)
  
    # pool.terminate() # 立即终止
  
    pool.join()
  
    pass
  
----------
  
"C:\Program Files\Python3\python.exe" C:/temp/s13day11/day11/s16.py
  
0 b
  
1 b
  
2 b
  
3 b
  
4 b
  
0 a
  
5 b
  
1 a
  
6 b
  
2 a
  
7 b
  
3 a
  
8 b
  
4 a
  
9 b
  
5 a
  
10 b
  
6 a
  
11 b
  
7 a
  
8 a
  
12 b
  
13 b
  
9 a
  
14 b
  
10 a
  
15 b
  
11 a
  
16 b
  
13 a
  
12 a
  
18 b
  
17 b
  
14 a
  
19 b
  
15 a
  
20 b
  
16 a
  
21 b
  
17 a
  
18 a
  
22 b
  
23 b
  
19 a
  
24 b
  
20 a
  
25 b
  
21 a
  
26 b
  
22 a
  
27 b
  
23 a
  
28 b
  
24 a
  
29 b
  
25 a
  
26 a
  
27 a
  
28 a
  
29 a
  注意和线程类似,进程里面也可以使用join(),确保主进程阻塞在这里直到所有的子进程都结束。



运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-552607-1-1.html 上篇帖子: python之优雅的函数定义和调用 下篇帖子: python,day13-堡垒机
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表