在python中有三种方式用于实现进程
多进程中, 每个进程中所有数据( 包括全局变量) 都各有拥有⼀份, 互不影响

1.fork()方法

  1. ret = os.fork()
  2. if ret == 0:
  3. #子进程
  4. else:
  5. #父进程

这是python中实现进程最底层的方法,其他两种从根本上也是利用fork()方法来实现的,下面是fork()方法的原理示意图

getpid()、getppid()方法
  1. import os
  2. rpid = os.fork()
  3. if rpid<0:
  4. print("fork调⽤失败。 ")
  5. elif rpid == 0:
  6. print("我是⼦进程( %s) , 我的⽗进程是(%s) "%(os.getpid(),os.getppid()))
  7. x+=1
  8. else:
  9. print("我是⽗进程( %s) , 我的⼦进程是( %s) "%(os.getpid(),rpid))
  10. print("⽗⼦进程都可以执⾏这⾥的代码")

运行结果:

  1. 我是⽗进程( 19360) , 我的⼦进程是( 19361)
  2. ⽗⼦进程都可以执⾏这⾥的代码
  3. 我是⼦进程( 19361) , 我的⽗进程是( 19360)
  4. ⽗⼦进程都可以执⾏这⾥的代码
注意:
(1)其中os.fork()的返回值ret在第一行执行后,会开辟另外一个子进程,然后父进程跟子进程同时从此句往下执行,对于子进程来说,ret值是0,对于父进程来说ret值是一个大于0的值,这个值实际上就是新开子进程的pid.
(2)此种开辟进程的方式不会发生堵塞,也就是父进程结束并不会影响子进程的继续执行。实际上是根据操作系统的调度算法来实现的,父子进程相互不影响。
多进程修改全局变量
  1. #coding=utf-8
  2. import os
  3. import time
  4. num = 0
  5. # 注意, fork函数, 只在Unix/Linux/Mac上运⾏, windows不可以
  6. pid = os.fork()
  7. if pid == 0:
  8. num+=1
  9. print('哈哈1---num=%d'%num)
  10. else:
  11. time.sleep(1)
  12. num+=1
  13. print('哈哈2---num=%d'%num)

运行结果

  1. 哈哈1---num=1
  2. 哈哈2---num=1
  3. #多进程不共享全局变量
多次fork()问题
结论:多次fork()会有多个进程生成,生成规则同上。
2,Process方法
python是跨平台的,所以自然肯定会为我们提供实现多进程的库,毕竟在win里面用不了fork()。此方法需要导入对应模块
  1. from multiprocessing import Process
  2. p1=Process(target=xxxx)
  3. p1.start()
这个方法常用场景是使用少量进程做主动服务,如qq客户端,等这样的可以开多个。
还可以继承Process模块并实现run方法来调用,此时xxxx方法等价于run方法执行的内容,在重写过run方法后,在执行子类实例对象的start方法时,会自动调用实现的run方法,这个跟java里面也是类似的。
注意,此种方法子进程不结束,父进程也会堵塞,也就是等子进程都结束后,父进程才会结束,通常应用于进程间的同步。
代码实现演示
  1. #coding=utf-8
  2. from multiprocessing import Process
  3. import os
  4. # ⼦进程要执⾏的代码
  5. def run_proc(name):
  6. print('⼦进程运⾏中, name= %s ,pid=%d...' % (name, os.getpid()))
  7. if __name__=='__main__':
  8. print('⽗进程 %d.' % os.getpid())
  9. p = Process(target=run_proc, args=('test',))
  10. print('⼦进程将要执⾏')
  11. p.start()
  12. p.join()
  13. print('⼦进程已结束')
运行结果
  1. ⽗进程 4857.
  2. ⼦进程将要执⾏
  3. ⼦进程运⾏中, name= test ,pid=4858...
  4. ⼦进程已结束
Process类常⽤⽅法:
is_alive(): 判断进程实例是否还在执⾏;
join([timeout]): 是否等待进程实例执⾏结束, 或等待多少秒;
start(): 启动进程实例( 创建⼦进程) ;
run(): 如果没有给定target参数, 对这个对象调⽤start()⽅法时, 就将执⾏对象中的run()⽅法;
terminate(): 不管任务是否完成, ⽴即终⽌;
3,利用进程池Pool
当需要创建的⼦进程数量不多时, 可以直接利⽤multiprocessing中的Process动态成⽣多个进程, 但如果是上百甚⾄上千个⽬标, ⼿动的去创建进程的⼯作量巨⼤, 此时就可以⽤到multiprocessing模块提供的Pool⽅法。此方法也需导入对应模块
  1. from multiprocessing import Pool
  2. pool=Pool(3)
  3. pool.apply_async(xxxx)
xxxx表示要在进程中运行的代码块或方法、函数
此方法可以用来做服务器端的响应,往往主进程比较少,而Pool()中的参数值,也就是进程池的大小,真正的任务都在子进程中执行。
使用示例
  1. from multiprocessing import Pool
  2. import os,time,random
  3. def worker(msg):
  4. t_start = time.time()
  5. print("%s开始执⾏,进程号为%d"%(msg,os.getpid()))
  6. #random.random()随机⽣成0~1之间的浮点数
  7. time.sleep(random.random()*2)
  8. t_stop = time.time()
  9. print(msg,"执⾏完毕, 耗时%0.2f"%(t_stop-t_start))
  10. po=Pool(3) #定义⼀个进程池, 最⼤进程数3
  11. for i in range(0,10):
  12. #Pool.apply_async(要调⽤的⽬标,(传递给⽬标的参数元祖,))
  13. #每次循环将会⽤空闲出来的⼦进程去调⽤⽬标
  14. po.apply_async(worker,(i,))
  15. print("----start----")
  16. po.close() #关闭进程池, 关闭后po不再接收新的请求
  17. po.join() #等待po中所有⼦进程执⾏完成, 必须放在close语句之后
  18. print("-----end-----")

运行结果

  1. ----start----
  2. ----start----
  3. 0开始执⾏,进程号为5025
  4. ----start----
  5. 1开始执⾏,进程号为5026
  6. ----start----
  7. ----start----
  8. ----start----
  9. ----start----
  10. ----start----
  11. ----start----
  12. ----start----
  13. 2开始执⾏,进程号为5027
  14. 0 执⾏完毕, 耗时0.58
  15. 3开始执⾏,进程号为5025
  16. 1 执⾏完毕, 耗时0.70
  17. 4开始执⾏,进程号为5026
  18. 2 执⾏完毕, 耗时1.36
  19. 5开始执⾏,进程号为5027
  20. 3 执⾏完毕, 耗时1.03
  21. 6开始执⾏,进程号为5025
  22. 4 执⾏完毕, 耗时1.12
  23. 7开始执⾏,进程号为5026
  24. 5 执⾏完毕, 耗时1.25
  25. 8开始执⾏,进程号为5027
  26. 7 执⾏完毕, 耗时1.28
  27. 9开始执⾏,进程号为5026
  28. 6 执⾏完毕, 耗时1.91
  29. 8 执⾏完毕, 耗时1.23
  30. 9 执⾏完毕, 耗时1.38
  31. -----end-----
上面使用的是非堵塞方法,如果使用aply(),则是堵塞方法
  1. from multiprocessing import Pool
  2. import os,time,random
  3. def worker(msg):
  4. t_start = time.time()
  5. print("%s开始执⾏,进程号为%d"%(msg,os.getpid()))
  6. #random.random()随机⽣成0~1之间的浮点数
  7. time.sleep(random.random()*2)
  8. t_stop = time.time()
  9. print(msg,"执⾏完毕, 耗时%0.2f"%(t_stop-t_start))
  10. po=Pool(3) #定义⼀个进程池, 最⼤进程数3
  11. for i in range(0,10):
  12. po.apply(worker,(i,))
  13. print("----start----")
  14. po.close() #关闭进程池, 关闭后po不再接收新的请求
  15. po.join() #等待po中所有⼦进程执⾏完成, 必须放在close语句之后
  16. print("-----end-----")

运行结果

  1. 0开始执⾏,进程号为5280
  2. 0 执⾏完毕, 耗时0.91
  3. 1开始执⾏,进程号为5281
  4. 1 执⾏完毕, 耗时1.59
  5. 2开始执⾏,进程号为5282
  6. 2 执⾏完毕, 耗时1.25
  7. 3开始执⾏,进程号为5280
  8. 3 执⾏完毕, 耗时0.53
  9. 4开始执⾏,进程号为5281
  10. 4 执⾏完毕, 耗时1.49
  11. 5开始执⾏,进程号为5282
  12. 5 执⾏完毕, 耗时0.18
  13. 6开始执⾏,进程号为5280
  14. 6 执⾏完毕, 耗时1.51
  15. 7开始执⾏,进程号为5281
  16. 7 执⾏完毕, 耗时0.88
  17. 8开始执⾏,进程号为5282
  18. 8 执⾏完毕, 耗时1.08
  19. 9开始执⾏,进程号为5280
  20. 9 执⾏完毕, 耗时0.12
  21. ----start----
  22. -----end-----
multiprocessing.Pool常⽤函数解析:
apply_async(func[, args[, kwds]]) : 使⽤⾮阻塞⽅式调⽤func( 并⾏执⾏, 堵塞⽅式必须等待上⼀个进程退出才能执⾏下⼀个进程) , args为传递给func的参数列表, kwds为传递给func的关键字参数列表;
apply(func[, args[, kwds]]): 使⽤阻塞⽅式调⽤funcclose(): 关闭Pool, 使其不再接受新的任务;
terminate(): 不管任务是否完成, ⽴即终⽌;
join(): 主进程阻塞, 等待⼦进程的退出, 必须在close或terminate之后使⽤;
版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/hu_lichao/article/details/75249055

python实现进程的三种方式及其区别的更多相关文章

  1. python核心高级学习总结3-------python实现进程的三种方式及其区别

    python实现进程的三种方式及其区别 在python中有三种方式用于实现进程 多进程中, 每个进程中所有数据( 包括全局变量) 都各有拥有⼀份, 互不影响 1.fork()方法 ret = os.f ...

  2. Python—创建进程的三种方式

    方式一:os.fork() 子进程是从os.fork得到的值,然后赋值开始执行的.即子进程不执行os.fork,从得到的值开始执行. 父进程中fork之前的内容子进程同样会复制,但父子进程空间独立,f ...

  3. python实现单例模式的三种方式及相关知识解释

    python实现单例模式的三种方式及相关知识解释 模块模式 装饰器模式 父类重写new继承 单例模式作为最常用的设计模式,在面试中很可能遇到要求手写.从最近的学习python的经验而言,singlet ...

  4. Python实现定时执行任务的三种方式简单示例

    本文实例讲述了Python实现定时执行任务的三种方式.分享给大家供大家参考,具体如下: 1.定时任务代码 import time,os,sched schedule = sched.scheduler ...

  5. Python格式化输出的三种方式

    Python格式化输出的三种方式 一.占位符 程序中经常会有这样场景:要求用户输入信息,然后打印成固定的格式比如要求用户输入用户名和年龄,然后打印如下格式:My name is xxx,my age ...

  6. Java实现线程的三种方式和区别

    Java实现线程的三种方式和区别 Java实现线程的三种方式: 继承Thread 实现Runnable接口 实现Callable接口 区别: 第一种方式继承Thread就不能继承其他类了,后面两种可以 ...

  7. 记住 Python 变量类型的三种方式

    title: 记住变量类型的三种方式 date: 2017-06-11 15:25:03 tags: ['Python'] category: ['Python'] toc: true comment ...

  8. javascript函数命名的三种方式及区别

    1, function fn(val1,val2) { alert(val1+val2); } fn(1,2); 2, var fn=function() { alert(val1+val2); } ...

  9. React创建组件的三种方式及其区别

    内容转载于http://www.cnblogs.com/wonyun/p/5930333.html React推出后,出于不同的原因先后出现三种定义react组件的方式,殊途同归; 具体的三种方式: ...

随机推荐

  1. ISBN号码(0)<P2008_1>

    ISBN号码    (isbn.pas/c/cpp) [问题描述] 每一本正式出版的图书都有一个ISBN号码与之对应,ISBN码包括9位数字.1位识别码和3位分隔符,其规定格式如“x-xxx-xxxx ...

  2. 十四 OGNL的概述

    1 什么是OGNL? 对象图导航语言(对象图,以任意一个对象为根,通过OGNL;可以访问与这个对象关联的其他对象).比EL表达式强大很多倍. 可以存取对象的任意属性.调用对象的方法,遍历整个对象的结构 ...

  3. mysql mvcc 的理解

    mvcc 全称 multiple version concurrency control 多版本并发控制,是数据库领域比较常用的一种非锁并发技术. mysql 的innodb中,在RR.RC级别会使用 ...

  4. SystemVerilog for design 笔记(二)

    转载请标明出处 1. System Verilog文本值和数据类型 1.1. 增强的文本值赋值 相对于verilog,SV在文本值赋值时可以1.无需指定进制    2.赋值可以是逻辑1 用法: reg ...

  5. 代码审计变成CTF

    0x01 代码审计中的信息收集 一个cms代码量确实不少,通读代码耗时长,效果也不一定好.而一个功能点如果之前出过漏洞,特别是多次出现漏洞的地方,证明开发者对这个漏洞的理解不充分,很容易再次绕过补丁. ...

  6. 108、Java中String类之字符串文本替换

    01.代码如下: package TIANPAN; /** * 此处为文档注释 * * @author 田攀 微信382477247 */ public class TestDemo { public ...

  7. C++11并发编程4------线程间共享数据

    举个例子: 刚参加工作的你,只能租房住,嫌房租贵就和别人合租了,两个人住一起只有一个洗手间,每天早上起床的时候,如果你室友在洗手间,你就只能等着,如果你强行进去,那画面就不可描述了.同样的问题,如果多 ...

  8. 使用mybase、Typora搭配坚果云实现个人云笔记

    如果我们没有使用印象笔记.有道云之类的云笔记,那么就会遇到一个问题,比如我在公司是用的公司的电脑,然后下班回家用的自己的电脑,那么我在公司写的文档,比如markdown 文件,mybase知识管理工具 ...

  9. 一文解读CDN (转)

    如今这个移动互联网时代,越来越多的人使用手机观看视频,丰富自己的娱乐生活. 可是,大家在追剧的时候,有没有想过一个问题——为什么有时候明明自己手机的网速很快,但观看视频时,仍然卡顿? 回答这个问题之前 ...

  10. 页面自动执行js的3种方法

    1.最简单的调用方式,直接写到html的body标签里面:   <html> <body onload="load();"> </body> & ...