1、创建自己的进程类

import multiprocessing as mu
import time


class ClockProcess(mu.Process):
    def __init__(self, value):
        self.value = value
        mu.Process.__init__(self)

    # 在自定义的进程类中重写父类的方法
    def run(self):
        n = 5
        while n > 0:
            print('The time is {}'.format(time.ctime()))
            time.sleep(self.value)
            n -= 1


# 用自己的进程类创建进程
p = ClockProcess(1)
# 自动执行run方法
p.start()
p.join()

2、多进程

    优点:

        并行多个任务,提高运行效率


        空间独立,数据安全,创建方便


    缺点:

        进程创建销毁的过程中消耗较多的计算机资源


3、进程池

    在需要频繁的创建删除较多进程的情况下,导致计算机资源消耗过多



    1、进程池技术如何处理

        1、创建进程池,在池内放入适量的进程


        2、将事件加入进程池的等待队列


        3、使用进程池中的进程不断处理事件


        4、所有事件处理后,回收关闭进程池


    2、from multiprocessing import Pool



        1、Pool()

            功能:


                创建进程池


            参数:


                processes : 制定进程池中进程数量


            返回:


                得到进程池对象


        2、pool.apply_async()

            功能:


                异步方式将事件放入进程池执行


            参数:


                func : 要执行的事件函数


                args : 同Process中args给函数传参


                kwds : 同Process中kwargs给函数传参


            返回值:


                返回一个对象,该对象可以通过get()方法得到func函数的返回值


        3、pool.close()

            功能:


                关闭进程池,使其无法加入新的事件


        4、pool.join()

            功能:


                阻塞等待进程池退出(当所有事件处理完毕后)


            参数:


                无


           

注:要先close,后join


    示例:


from multiprocessing import Pool
import time
import os


def worker(msg):
    time.sleep(2)
    print(msg)
    return msg + ' over'


# 创建进程池,启动4个进程
pool = Pool(processes=4)

result = []
# 放入事件
for i in range(10):
    msg = 'hello %d' % i
    # 加入事件后进程就会立即操作事件
    # apply_async 的返回值对象,该对象可以获取worker的返回结果
    r = pool.apply_async(worker, (msg,))
    result.append(r)

# 关闭进程池
pool.close()

# 阻塞等待回收
pool.join()

# 通过apply_async()返回对象get()方法获取返回值
for i in result:
    print(i.get())
        5、pool.apply()

            用法和apply_async一样,只是需要顺序执行,一个事件结束再执行另一个事件


            返回值:


                无


        6、pool.map(func,iter)

            功能:


                类似于内建函数map 将第二个参数的迭代书传递给第一个参数的函数执行。


                同时兼容了使用进程池执行


            返回值:


                返回func函数的返回值列表



            示例:


from multiprocessing import Pool
import time


def fun(fn):
    time.sleep(1)
    return fn * fn


test = [1, 2, 3, 4, 5, 6]
pool = Pool(processes=4)
r = pool.map(fun, test)
# 等同于
# r=[]
# for i in test:
#     res=pool.apply_async(fun,(i,))
#     r.append(res.get())

print(r)
pool.close()
pool.join()

4、进程间通信

    方法:

        1、磁盘交互:

            1、速度慢


            2、不安全


        2、socket (已学)

            本地套接字


        3、管道(pipe)

            在内存中开辟一块空间,对多个进程可见,通过管道多进程间进行通信



            multiprocessing.Pipe


                1、fd1,fd2=Pipe(duplex=True)

                    功能:


                        创建一个进程间通信的管道


                    参数:


                        duplex默认为True   表示双向管道


                        设置为False        表示单项管道


                    返回值:


                        两个管道流对象,表示管道的两端


                        如果是双向管道则两个均可读写


                        如果为单项管道则fd1只能读,fd2只能写


                2、fd1.recv()

                    功能:


                        接收消息(每次接收一条)


                    参数:


                        无


                    返回值:


                        接收到的消息


                    注:如果管道内没有消息会阻塞



                3、fd2.send(data)

                    功能:


                        发送消息(可以是字符串或其他类型)


                    参数:


                        要发出的内容


                    注:如果没有接收端则管道破裂


                示例:


import multiprocessing as mu
import os
import time

# 如果参数为False则fd1只能revc,fd2只能send
# fd1, fd2 = mu.Pipe()

# 创建一个双向管道
fd1, fd2 = mu.Pipe()


def fun(name):
    time.sleep(1)
    # 发送字符串到管道
    fd1.send({'hello ' :i})
    print(os.getppid(), '--------', os.getpid())


jobs = []
for i in range(5):
    p = mu.Process(target=fun, args=(i,))
    jobs.append(p)
    p.start()
# 接收子进程发送的消息
for i in range(5):
    data = fd2.recv()
    print(data)

for i in jobs:
    i.join()
        4、消息队列
            1、队列

                先进先出


                在内存中开辟队列模型,用来存放消息,任何拥有队列的进程都可以存取消息


            2、创建队列

                multiprocessing.Queue()


                1、q=Queue(maxsize=0)


                    功能:


                        创建一个队列


                    参数:


                        maxsize 默认为0    表示队列可存放消息由内存而定


                                    >0    表示队列最多存放多少条消息


                    返回值:


                        返回消息队列对象


                2、q.put()


                    功能:


                        向队列中存放消息


                    参数:


                        要存放的消息(字符串 整数 列表)


                    注:当队列满时会阻塞


                3、q.full()


                    功能:


                        判断队列是否为满 满返回True


                4、q.get()


                    功能:


                        向队列取出消息


                    返回值:


                        取出的消息


                    注:当队列为空时会阻塞


                5、q.empty()


                    功能:


                        判断队列是否为空,空返回True


                6、q.qsize()


                    功能:


                        得到当前队列中消息的个数


               

注:put get中均有可选参数block和timeout

                   block默认为True 表示阻塞函数,如果设置为False则不阻塞

                   timeout block为True时,设置超时时间


        示例:

from multiprocessing import Queue

# 创建队列
q = Queue(3)
q.put(1)
print(q.full())
q.put(2)
q.put(3)
print(q.full())
# 设置超时时间为3秒
q.put(4, timeout=3)
print(q.get())
print('队列中还有%d条消息' % q.qsize())
print(q.empty())
q.close()  # 关闭队列

示例二


from multiprocessing import Process, Queue
import time

# 创建消息队列
q = Queue()


def fun1():
    time.sleep(1)
    q.put('我是进程一')


def fun2():
    time.sleep(2)
    print('取消息:', q.get())


p1 = Process(target=fun1)
p2 = Process(target=fun2)

p1.start()
p2.start()

p1.join()
p2.join()
        3、共享内存

            在内存中开辟一段空间,存储数据,对多个进程可见。


            每次写入内存的数据会覆盖之前的内容。


            由于对内存格式化较少,所以存取速度快。


            1、创建共享内存

                from multiprocessing import Value, Array


            2、obj = Value(ctype,obj)

                功能:


                    开辟共享内存空间


                参数:


                    ctype   str   要转变的c类型   对照ctype表


                    obj     写入共享内存的初始值


                返回值:


                    返回一个共享内存的对象


                obj.value   即可得到共享内存中的值



                示例:


from multiprocessing import Value, Process
import time
import random


# 向共享内存存钱
def deposize(money):
    for i in range(100):
        time.sleep(0.03)
        money.value += random.randint(1, 200)


# 向共享内存取钱
def withdraw(money):
    for i in range(100):
        time.sleep(0.02)
        money.value += random.randint(1, 150)


# 创建共享内存对象
money = Value('i', 2000)

d = Process(target=deposize, args=(money,))
w = Process(target=withdraw, args=(money,))
d.start()
w.start()
d.join()
w.join()
print(money.value)
            3、obj=Array(ctype,obj)

                功能:


                    开辟共享内存空间


                参数:


                    ctype   要转换的类型


                    obj     存入到共享内存中的数据


                            是一个列表,要求列表中数据类型一致


                            正整数,则表示开辟一个多大的序列空间


                返回值:


                    返回一个共享内存对象


                示例:


from multiprocessing import Array, Process
import time


def fun(shm):
    for i in shm:
        print(i)
    shm[2] = 1000


# 开辟共享内存空间,可容纳留个整数
# 初始值是[1, 2, 3, 4, 5, 6]
# shm = Array('i', [1, 2, 3, 4, 5, 6])

#表示在共享内存中开辟一个包含6个整形的空间
shm = Array('i',  6)
p = Process(target=fun, args=(shm,))
p.start()
p.join()
for i in shm:
    print(i)

管道,消息队列,共享内存三种进程方式间对比

 

管道

消息队列

共享内存

开辟空间

内存

内存

内存

读写方式

双向/单项

先进先出

操作覆盖内存

效率

一般

一般


应用

多用于亲缘进程

方便灵活广泛

较复杂

是否需要互斥机制



需要

        4、信号

            一个进程向另一个进程通过信号传递某种信息



                kill -l 查看信号


                kill -signame PID   给PID的进程发送信号


            1、关于信号:

                信号名称


                    系统定义,信号的名字


                信号含义


                    系统定义,信号的作用


                信号的默认处理方法


                    系统定义,信号给接收进程带来的行为,一般有 终止 暂停 忽略


            2.需要记住的信

               

python 自定义usersite Python 自定义进程池_进程池


python 自定义usersite Python 自定义进程池_进程池_02

         

          3、Python如何操作信号


                1、发送:


                    1、os.kill(pid,sig)


                        功能:


                            想一个进程发送一个信号


                        参数:


                            pid :要发送信号的进程pid


                            sig :要发送的信号


                    示例:


import os
import signal
# 向24051进程发送SIGKILL信号
os.kill(24051,signal.SIGKILL)

                    2、signal.alarm(sec)


                        功能:


                            向自身发送一个时钟信号 SIFALRM


                        参数:


                            sec 时钟秒数


                    示例


 

import signal
import time

# 3秒后向自己发送个SIGALRMXIN信号
signal.alarm(3)

# 阻塞等待一个信号
signal.pause()
while True:
    time.sleep(1)
    print('等待时钟……')



                注:信号属于异步通信方式,信号的发送不会影响进程的持续执行

                一个进程中只能同时有一个时钟,后面的时钟时间会覆盖前面的



                2、处理:


                    signal.pause()


                        功能:


                            阻塞等待一个信号的发生


                        示例


import signal
import time

# 3秒后向自己发送个SIGALRMXIN信号
signal.alarm(3)

# 阻塞等待一个信号
signal.pause()
while True:
	time.sleep(1)
	print('等待时钟……')