进程

功能一个进程就是一个任务,通过多进程能够实现多任务的执行。换句话说,多任务的需求,能:够通过多进程来满足。
定义:代码程序运行起来,就是进程,执行过程中创建的变量、消耗的内存空间等等统称为进程。进程实际上是个资源分配的单位。
注意:

  1. 底层中,不同的操作系统对进程的处理顺序等是不同的。
  2. 进程之间数据是不共享的

一、创建经常的三种方法,以及他们的区别

1.unixt系统的底层fork()进程

python pool和ProcessPoolExecutor有什么区别 processing和python什么关系_进程池


父进程、子进程执行顺序没有规律,完全取决于操作系统的调度算法。

2.multiprocessing模块创建Process类进程实例对象

python是跨平台语言,针对windows和unix系统进行封装了 一个multiprocessing模块。
调用方法: Process(target=函数名, (argvs元组,), (kwagrs字典))
Process([group [, target [, name [, args [, kwargs]]]]])
Process实例方法:join()用于等待进程实例结束,主进程才继续向下执行。

2.1Process类

代码:有join()

python pool和ProcessPoolExecutor有什么区别 processing和python什么关系_子进程_02


代码:无join()

python pool和ProcessPoolExecutor有什么区别 processing和python什么关系_消息队列_03


运行结果:可以看出,主进程执行完毕后,会等待进程实例执行完毕,再结束。

python pool和ProcessPoolExecutor有什么区别 processing和python什么关系_消息队列_04

2.2 自定义类创建进程的方法—Process的子类 :

功能,通过把一个复杂的任务放到一个类里面实现。

python pool和ProcessPoolExecutor有什么区别 processing和python什么关系_进程池_05

2.3相关文档(转)

python pool和ProcessPoolExecutor有什么区别 processing和python什么关系_子进程_06

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
-------主进程---完成结束----

多任务进程池的方式,主进程不会等待进程池的任务,一旦主进程完成,程序就结束,因此要记得关闭进程池,然后阻塞。

python pool和ProcessPoolExecutor有什么区别 processing和python什么关系_进程池_07

二、进程之间的通信(Queue)

进程之间的通讯方式有很多种:命名管道,无名管道,共享内存,队列,socket等方法。

1.Queue队列

队列通讯可以容纳任何数据类型。

相关文档:(转)

python pool和ProcessPoolExecutor有什么区别 processing和python什么关系_进程池_08


代码:

"""队列通讯相关方法"""
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号进程负责收回资源。