并发:一个处理器同时处理多个任务。

并行:多个处理器或者是多核的处理器同时处理多个不同的任务.

fork创建子进程

import os
import time #fork出一个子进程,子进程也从这一行开始执行
ret = os.fork()
if ret == 0:
while True:
print("---1---")
time.sleep(1)
else:
while True:
print("---2---")
time.sleep(1)

  输出

---2---
---1---
---1---
---2---
---2---
---1---
---1---
---2---
...

  

查看子进程id

import os
import time ret = os.fork()
if ret != 0:
print("---父进程---%d---"%os.getpid())
else:  #ret等于0的是子进程
print("---子进程---%d---父进程---%d---"%(os.getpid(), os.getppid()))

  输出

---父进程---5142---
---子进程---5143---父进程---5142---

  

全局变量在多个进程之间不共享

import os
import time g_num = 100
ret = os.fork() if ret == 0:
print("---process-1---")
g_num += 1
print("---process-1 g_num=%d---"%g_num)
else:
time.sleep(3)
print("---process-2---")
print("---process-2 g_num=%d---"%g_num)

  输出

---process-1---
---process-1 g_num=101---
---process-2---
---process-2 g_num=100---

  

多个fork

import os
import time ret = os.fork()
if ret != 0:
print("---1---")
else:
print("---2---") ret = os.fork()
if ret != 0:
print("---11---")
else:
print("---22---")

  输出

---1---
---2---
---11---
---22---
---22---
---11---

  

fork炸弹

import os
while True:
os.fork()
print("---1---")

注意:

fork不能在windows下运行

fork创建的主进程不会等到子进程运行结束后再推出

process

Process语法结构如下:
Process([group[,target[,name[,args[,kwargs]]]]])
target:表示这个进程实例所调用对象;
args:表示调用对象的位置参数元组;
kwargs:表示调用对象的关键字参数字典;
name:为当前进程实例的别名;
group:大多数情况下用不到;

Process类常用方法:
is_alive():判断进程实例是否还在执⾏;
join([timeout]):是否等待进程实例执行结束,或等待多少秒;
start():启动进程实例(创建子进程);
run():如果没有给定target参数,对这个对象调用start()方法时,就将执 ⾏对象中的run()⽅法;
terminate():不管任务是否完成,立即终止;

Process类常用属性:
name:当前进程实例别名,默认为Process-N,N为从1开始递增的整数;
pid:当前进程实例的PID值;

process创建子进程

process可以在windows上运行

from multiprocessing import Process

import time

def test():
while True:
print("---test---")
time.sleep(1) if __name__ == "__main__":
p = Process(target=test)
p.start()
while True:
print("---main---")
time.sleep(1)

  输出

---main---
---test---
---main---
---test---
...

  

创建的子进程和主进程结束

from multiprocessing import Process
import time def test():
for i in range(5):
print("---test---")
time.sleep(1)
if __name__ == "__main__":
p = Process(target=test)
p.start() #让这个进程开始执行test函数里的代码
print("---main---")

  输出

---main---
---test---
---test---
---test---
---test---
---test---

  

给target函数传参数

from multiprocessing import Process
import os def test(num):
print("pid=%d,ppid=%d,num=%d"%(os.getpid(),os.getppid(),num)) if __name__ == "__main__":
p = Process(target=test, args=(100,))
p.start()
print("---main-pid=%d---"%os.getpid())

  输出

---main-pid=14252---
pid=18284,ppid=14252,num=100

  

join

from multiprocessing import Process
import time def test():
for i in range(5):
print("---%d---"%i)
time.sleep(1) if __name__ == "__main__":
p = Process(target=test)
p.start()
p.join()#阻塞,子进程运行结束后,才向下继续执行
print("---main---")

  输出

---0---
---1---
---2---
---3---
---4---
---main---

  

第二种process创建子进程的方法

from multiprocessing import Process
import time class MyNewProcess(Process):
def run(self):
while True:
print("---1---")
time.sleep(1) if __name__ == "__main__":
p = MyNewProcess()
p.start() while True:
print("---main---")
time.sleep(1)

  输出

---main---
---1---
---main---
---1---
---main---
---1---
---main---
---1---
...

  

进程池

from multiprocessing import Pool
import os
import time
def test(num):
print("pid=%d,ppid=%d,num=%d"%(os.getpid(),os.getppid(),num))
time.sleep(1) if __name__ == "__main__":
pool = Pool(3) for i in range(10):
print("---%d---"%i)
pool.apply_async(test,(i,)) pool.close()
pool.join() #join保证子进程运行结束后,进程池才退出

进程间通信-Queue
Process之间有时需要通信,操作系统提供了很多机制来实现进程间的通信。

可以使⽤multiprocessing模块的Queue实现多进程之间的数据传递,Queue 本身是⼀个消息列队程序。

初始化Queue()对象时(例如:q=Queue()),若括号中没有指定最⼤可接收 的消息数量,或数量为负值,那么就代表可接受的消息数量没有上限(直到 内存的尽头);
Queue.qsize():返回当前队列包含的消息数量;
Queue.empty():如果队列为空,返回True,反之False ;
Queue.full():如果队列满了,返回True,反之False;
Queue.get([block[, timeout]]):获取队列中的⼀条消息,然后将其从列队 中移除,block默认值为True;

  • 1)如果block使⽤默认值,且没有设置timeout(单位秒),消息列队如果为 空,此时程序将被阻塞(停在读取状态),直到从消息列队读到消息为⽌, 如果设置了timeout,则会等待timeout秒,若还没读取到任何消息,则抛 出"Queue.Empty"异常;
  • 2)如果block值为False,消息列队如果为空,则会⽴刻抛 出"Queue.Empty"异常;

Queue.get_nowait():相当Queue.get(False);

Queue.put(item,[block[, timeout]]):将item消息写⼊队列,block默认值 为True;

  • 1)如果block使⽤默认值,且没有设置timeout(单位秒),消息列队如果已 经没有空间可写⼊,此时程序将被阻塞(停在写⼊状态),直到从消息列队 腾出空间为⽌,如果设置了timeout,则会等待timeout秒,若还没空间,则抛 出"Queue.Full"异常;
  • 2)如果block值为False,消息列队如果没有空间可写⼊,则会⽴刻抛 出"Queue.Full"异常;

Queue.put_nowait(item):相当Queue.put(item, False);

实例一

from	multiprocessing	import
Queue q=Queue(3) #初始化⼀个Queue对象,最多可接收三条put消息
q.put("消息1")
q.put("消息2")
print(q.full()) #False
q.put("消息3")
print(q.full()) #True #因为消息列队已满下⾯的try都会抛出异常,第⼀个try会等待2秒后再抛出异常,第⼆个Try会⽴
try:
q.put("消息4",True,2)
except:
print("消息列队已满,现有消息数量:%s"%q.qsize()) try:
q.put_nowait("消息4")
except:
print("消息列队已满,现有消息数量:%s"%q.qsize()) #推荐的⽅式,先判断消息列队是否已满,再写⼊
if not q.full():
q.put_nowait("消息4")
#读取消息时,先判断消息列队是否为空,再读取
if not q.empty():
for i in range(q.qsize()):
print(q.get_nowait())

  输出

False
True
消息列队已满,现有消息数量:3
消息列队已满,现有消息数量:3
消息1
消息2
消息3

  

实例二

from multiprocessing import Process, Queue
import os, time, random # 写数据进程执行的代码:
def write(q):
for value in ['A', 'B', 'C']:
print('Put %s to queue...' % value)
q.put(value)
time.sleep(random.random()) # 读数据进程执行的代码:
def read(q):
while True:
if not q.empty():
value = q.get(True)
print('Get %s from queue.' % value)
time.sleep(random.random())
else:
break if __name__ == '__main__':
# 父进程创建Queue,并传给各个子进程:
q = Queue()
pw = Process(target=write, args=(q,))
pr = Process(target=read, args=(q,))
# 启动子进程pw,写入:
pw.start()
# 等待pw结束:
pw.join()
# 启动子进程pr,读取:
pr.start()
pr.join()
# pr进程里是死循环,无法等待其结束,只能强行终止:
print("")
print("所有数据都写入并且读完")

  输出

Put A to queue...
Put B to queue...
Put C to queue...
Get A from queue.
Get B from queue.
Get C from queue. 所有数据都写入并且读完

  

进程池中的Queue
如果要使⽤Pool创建进程,就需要使⽤multiprocessing.Manager()中的 Queue(),⽽不是multiprocessing.Queue(),否则会得到⼀条如下的错误信息:

# 修改import中的Queue为Manager
from multiprocessing import Manager, Pool
import os def reader(q):
print("reader启动(%s),父进程为(%s) " % (os.getpid(), os.getppid()))
for i in range(q.qsize()):
print("reader从Queue获取到消息:%s " % q.get(True)) def writer(q):
print("writer启动(%s),父进程为(%s) " % (os.getpid(), os.getppid()))
for i in "dongGe":
q.put(i) if __name__ == "__main__":
print("(%s) start " % os.getpid())
q = Manager().Queue() # 使用Manager中的Queue来初始化
po = Pool()
# 使用阻塞模式创建进程,这样就不需要在reader中使用死循环了,可以让writer完全执行完
po.apply(writer, (q,))
po.apply(reader, (q,))
po.close()
po.join()
print("(%s) End" % os.getpid())

  输出

(15004)	start
writer启动(10232),父进程为(15004)
reader启动(1612),父进程为(15004)
reader从Queue获取到消息:d
reader从Queue获取到消息:o
reader从Queue获取到消息:n
reader从Queue获取到消息:g
reader从Queue获取到消息:G
reader从Queue获取到消息:e
(15004) End

  

  

  

多任务fork、multiprocessing、进程池、进程间通信-Queue的更多相关文章

  1. python进程池 使用Queue实现计数功能

    多进程中各个进程间相互隔离,进程间通信需要使用到通道. 多进程中使用Queue实现进程中通信 from multiprocessing import Process,Queue import time ...

  2. python3下multiprocessing、threading和gevent性能对比----暨进程池、线程池和协程池性能对比

    python3下multiprocessing.threading和gevent性能对比----暨进程池.线程池和协程池性能对比   标签: python3 / 线程池 / multiprocessi ...

  3. 41.进程池--Pool

    进程池 方便创建,管理进程,单独进程的Process创建,需要手动开启,维护任务函数,以及释放回收 进程池不需要这么麻烦,进程提前创建好,未来在使用的时候,可以直接给与任务函数 某个进程池中的任务结束 ...

  4. Python--线程队列(queue)、multiprocessing模块(进程对列Queue、管道(pipe)、进程池)、协程

    队列(queue) 队列只在多线程里有意义,是一种线程安全的数据结构. get与put方法 ''' 创建一个“队列”对象 import queue q = queue.Queue(maxsize = ...

  5. python并发编程之多进程(二):互斥锁(同步锁)&进程其他属性&进程间通信(queue)&生产者消费者模型

    一,互斥锁,同步锁 进程之间数据不共享,但是共享同一套文件系统,所以访问同一个文件,或同一个打印终端,是没有问题的, 竞争带来的结果就是错乱,如何控制,就是加锁处理 part1:多个进程共享同一打印终 ...

  6. python开发进程:互斥锁(同步锁)&进程其他属性&进程间通信(queue)&生产者消费者模型

    一,互斥锁,同步锁 进程之间数据不共享,但是共享同一套文件系统,所以访问同一个文件,或同一个打印终端,是没有问题的, 竞争带来的结果就是错乱,如何控制,就是加锁处理 part1:多个进程共享同一打印终 ...

  7. python基础-12 多线程queue 线程交互event 线程锁 自定义线程池 进程 进程锁 进程池 进程交互数据资源共享

    Python中的进程与线程 学习知识,我们不但要知其然,还是知其所以然.你做到了你就比别人NB. 我们先了解一下什么是进程和线程. 进程与线程的历史 我们都知道计算机是由硬件和软件组成的.硬件中的CP ...

  8. 2020.9.28 多进程multiprocess 进程池pool 子进程subprocess 进程间通信

    1.multiprocessing模块--跨平台版本的多进程模块 multiprocessing模块提供了一个Process类来代表一个进程对象,下面的例子演示了启动一个子进程并等待其结束: from ...

  9. 进程间通信(队列、管道)、消费者模型和进程池(apply,apply_async,map)

    一.队列(先进先出) 进程间通信:IPC(Inter-Process Communication) 队列是使用管道和锁定实现,所以Queue是多进程安全的队列,使用Queue可以实现多进程之间的数据传 ...

随机推荐

  1. Java中返回类型方法名

    继承父类,子类含有两个分别为boy.Girl类名. 返回是需要返回方法 则返回变量名Person class Person { void eat() {} void speak() {} } clas ...

  2. ChIP-seq 核心分析 下游分析

    http://icb.med.cornell.edu/wiki/index.php/Elementolab/ChIPseeqer_Tutorial [怪毛匠子 整理] ChIP-seq[核心分析 下游 ...

  3. 神州数码NAT地址转换配置

    实验要求:熟练掌握NAT地址转换的配置方法 拓扑如下 R1 enable 进入特权模式 config 进入全局模式 hostname R1 修改名称 interface s0/1 进入端口 ip ad ...

  4. Flask 上下文管理

    为什么用threading.local? 我们都知道线程是由进程创建出来的,CPU实际执行的也是线程,那么线程其实是没有自己独有的内存空间的,所有的线程共享进程的资源和空间,共享就会有冲突,对于多线程 ...

  5. oracle中left join,right join,inner join的坑

    本文主要是记录一下实际使用oracle中join查询遇到的坑 1.用到两张表,学生表和学年分数表,先建立 2.普通连接查询 INNER JOIN,查询每个学年有成绩的学生以及分数情况 LFET JOI ...

  6. Vue.js devtool插件安装后无法使用的解决办法【最简单有效的解决方法】

    在开发vue相关的项目时,使用vue devtools工具是一件极其有趣的事,你所有的操作都马上给你实时反馈. 然而有时候安装好的工具,在chrome中不显示. 在网上找过多次,一直没有找到有效解决方 ...

  7. CSS(3)多种方法实现水平垂直居中效果

    CSS实现水平垂直居中对齐 在CSS中实现水平居中,会比较简单.常见的,如果想实现inline元素或者inline-block元素水平居中,可以在其父级块级元素上设置text-align: cente ...

  8. Linux文件编辑vi、mkdir等

    1.进入vi的命令 vi filename :打开或新建文件,并将光标置于第一行首 vi +n filename :打开文件,并将光标置于第n行首 vi + filename :打开文件,并将光标置于 ...

  9. JavaScript属性(第三天)

    js语法非常灵活,这致使他非常好用,也造成它比较难掌握的地方: js中的值类型与引用类型在这里不做过多介绍,可以参照其他语言. js是可以动态添加属性的: var person={}; person. ...

  10. ubuntu typora使用学习

    typora使用方法 标题: 对于标题,直接用ctrl+对应数字就是第几级标题 文字格式: ctrl+B/I/U 进入加粗/倾斜/下划模式,不需要符号键入 居中的话 用 CENTER 列表引用: 可直 ...