学习笔记☞python3☞网络编程(六) ☞【创建自己的进程类,进程池,进程间通信(一)】

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.需要记住的信
               

         

          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('等待时钟……')


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值