进程
功能一个进程就是一个任务,通过多进程能够实现多任务的执行。换句话说,多任务的需求,能:够通过多进程来满足。
定义:代码程序运行起来,就是进程,执行过程中创建的变量、消耗的内存空间等等统称为进程。进程实际上是个资源分配的单位。
注意:
- 底层中,不同的操作系统对进程的处理顺序等是不同的。
- 进程之间数据是不共享的
一、创建经常的三种方法,以及他们的区别
1.unixt系统的底层fork()进程
父进程、子进程执行顺序没有规律,完全取决于操作系统的调度算法。
2.multiprocessing模块创建Process类进程实例对象
python是跨平台语言,针对windows和unix系统进行封装了 一个multiprocessing模块。
调用方法: Process(target=函数名, (argvs元组,), (kwagrs字典))
Process([group [, target [, name [, args [, kwargs]]]]])
Process实例方法:join()用于等待进程实例结束,主进程才继续向下执行。
2.1Process类
代码:有join()
代码:无join()
运行结果:可以看出,主进程执行完毕后,会等待进程实例执行完毕,再结束。
2.2 自定义类创建进程的方法—Process的子类 :
功能,通过把一个复杂的任务放到一个类里面实现。
2.3相关文档(转)
3.进程池
"""-1-进程池创建进程, 非阻塞式调用target"""
from multiprocessing import Pool
import time
import os
def worker(num):
for i in range(num):
print("-----子进程---i=:%d"%i)
def main():
#创建一个进程池,进程数量为3
p = Pool(3)
for i in range(5):
#用法类似于Process(target=,[,args=])
p.apply_async(worker,(i,)) #apply_async是非阻塞式调用target函数
#关闭进程池
p.close()
p.join()
print("-------主进程---完成结束----")
if __name__=='__main__':
main()
在windows下打印结果:
-----子进程---pid=4640---i=0
-----子进程---pid=13808---i=0-----子进程---pid=4640---i=0
-----子进程---pid=13808---i=1-----子进程---pid=4640---i=1
-----子进程---pid=4640---i=2
-----子进程---pid=4640---i=0
-----子进程---pid=4640---i=1
-----子进程---pid=4640---i=2
-----子进程---pid=4640---i=3
-------主进程---完成结束----
"""-2-进程池创建进程, 阻塞式调用target"""
from multiprocessing import Pool
import time
import os
def worker(num):
for i in range(num):
print("-----子进程---i=:%d"%i)
def main():
#创建一个进程池,进程数量为3
p = Pool(3)
for i in range(5):
#用法类似于Process(target=,[,args=])
p.apply(worker,(i,)) #apply是阻塞式调用target函数
#关闭进程池
p.close()
p.join()
print("-------主进程---完成结束----")
if __name__=='__main__':
main()
在windows下打印结果:
-----子进程---i=:0
-----子进程---i=:0
-----子进程---i=:1
-----子进程---i=:0
-----子进程---i=:1
-----子进程---i=:2
-----子进程---i=:0
-----子进程---i=:1
-----子进程---i=:2
-----子进程---i=:3
-------主进程---完成结束----
多任务进程池的方式,主进程不会等待进程池的任务,一旦主进程完成,程序就结束,因此要记得关闭进程池,然后阻塞。
二、进程之间的通信(Queue)
进程之间的通讯方式有很多种:命名管道,无名管道,共享内存,队列,socket等方法。
1.Queue队列
队列通讯可以容纳任何数据类型。
相关文档:(转)
代码:
"""队列通讯相关方法"""
from multiprocessing import Queue
import time, os
#创建一个最大可以接收2条信息的队列,
q = Queue(2)
print("-----队列是否为空:%s-----当前队列包含的消息数量:%d-----"%(q.empty(), q.qsize()))
q.put(5)
q.put([])
print("-----队列是否为满:%s-------当前队列包含的消息数量:%d-----"%(q.full(), q.qsize()))
#阻塞式,程序会等待,直到消息队列读取为止,因此不会异常报错
print(q.get())
#非阻塞式,不会等待,如果消息队列为空,则报错,程序退出。
print(q.get_nowait())
打印结果:
-----队列是否为空:True-----当前队列包含的消息数量:0-----
-----队列是否为满:True-------当前队列包含的消息数量:2-----
5
[]
1.1队列实现Process类进程间的通讯:
"""队列通讯Process"""
from multiprocessing import Queue, Process
import time, os, random
#写入数据
def write(q):
for i in ["A", "B", "C"]:
q.put(i)
print("----写入成功-----")
time.sleep(random.randint(0,2))
#读取数据
def read(q):
while True:
if not q.empty():
print("---------读取的消息: %s"%q.get_nowait())
else:
print("----消息队列读取完毕-----")
break
def main():
#创建一个消息队列
q = Queue(5)
#创建两个Process类进程
pw = Process(target=write, args=(q,))
pr = Process(target=read, args=(q,))
#启动进程
pw.start()
pw.join()
pr.start()
pr.join()
print("----------主进程执行完毕--------------")
if __name__=="__main__":
main()
打印结果:
----写入成功-----
----写入成功-----
----写入成功-----
---------读取的消息: A
---------读取的消息: B
---------读取的消息: C
----消息队列读取完毕-----
----------主进程执行完毕--------------
1.2队列实现Pool类进程池间的通讯—Manager类:
队列通讯进程池,在python中封装的类是Manager类中的Queue()方法,使用的方式跟Process类的Queue类一样。
"""队列Manager通讯进程池"""
from multiprocessing import Manager, Process
import time, os, random
#写入数据
def write(q):
for i in ["A", "B", "C"]:
q.put(i)
print("----写入成功-----")
time.sleep(random.randint(0,2))
#读取数据
def read(q):
while True:
time.sleep(random.randint(0,1))
if not q.empty():
time.sleep(random.randint(0, 2))
print("---------读取的消息: %s"%q.get_nowait())
time.sleep(random.randint(0, 2))
else:
print("----消息队列读取完毕-----")
break
def main():
#创建一个消息队列,使用得是Manager()中的Queue()方法
q = Manager().Queue()
#创建一个容量为3的进程池
po = Pool(5)
#写入数据进程
po.apply_async(write,args=(q,))
po.apply_async(read,args=(q,))
#关闭进程池>
po.close()
#阻塞
po.join()
print("----------主进程执行完毕--------------")
if __name__=="__main__":
main()
打印结果:
----写入成功-----
----写入成功-----
---------读取的消息: A
----写入成功-----
---------读取的消息: B
---------读取的消息: C
----消息队列读取完毕-----
----------主进程执行完毕--------------
其他
僵尸进程:子进程结束,父进程没有对子进程资源进行回收,称为将是僵尸进程。
孤儿进程:父进程结束,子进程未结束,称为孤儿进程。0号pid进程负责切换任务,1号pid进程负责创建进程。孤儿进程结束后,由1号进程负责收回资源。