python多进程基础详解

目录
  • 进程
  • 开启一个进程
  • JOIN方法
  • 进程之间空间隔离
  • 进程的常用方法
    • current_process 查看pid(进程id)
    • os.getpid() 查看进程id
    • 进程其他方法和属性
  • 守护进程
  • 互斥锁
  • 进程间通信(IPC机制)
  • JoinableQueue 来实现生产消费者
  • 总结

进程

什么是进程
进程指的是一个程序的运行过程,或者说一个正在执行的程序
所以说进程一种虚拟的概念,该虚拟概念起源操作系统

一个CPU 同一时刻只能执行一件事

开启一个进程

from  multiprocessing import Process
import time
def task(name):
    print('%s is running'%name)
    time.sleep(3)
    print('%s is done'%name)
# 开启子进程的操作必须放到
# if __name__ == '__main__'的子代码中
# 子进程不会再次加载
if __name__ == '__main__':
    p=Process(target=task,args=('小王',))
    # p=Process(target=task,kwargs={'name':'小王'})
    # print(p)
    p.start()
    # 主进程只是向操作系统发送了一个开启子进程的信号
    # p.start()
    # 1.操作系统先申请内存空间
    # 2.把主进程的数据拷贝到子进程里面
    # 3.调用cup才能运行里面的代码
    # 创造进程的开销大
    print('主')

JOIN方法

当前进程jion别的进程。当前进程就会等到别的进程执行完毕了才会继续开始往下执行

from multiprocessing import Process
import time

def task(name, n):
    print('%s is running' % name)
    time.sleep(n)
    print('%s is done' % name)

if __name__ == '__main__':
    start = time.time()
    p_l = []
    for i in range(1, 4):
        p = Process(target=task, args=('小王%s' % i, i))
        p_l.append(p)
        p.start()
    # 主进程等待子进程
    for p in p_l:
        p.join()
    print('主', (time.time() - start))

进程之间空间隔离

from multiprocessing import  Process
# 这个n是主进程里面的值
n = 100
def task():
    global n
    # 改的是子进程里面的全局变量
    # 主进程里面没有改
    n = 0
if __name__ == '__main__':
    p=Process(target=task)
    p.start()
    p.join()
    print(n)

进程的常用方法

current_process 查看pid(进程id)

# 1. 进程pid:每一个进程在操作系统内都有一个唯一的id号,称之为pid
from multiprocessing import Process, current_process
import time

def task():
    print('%s is running' % current_process().pid)
    time.sleep(3)
    print('%s is done' % current_process().pid)

# 开启子进程的操作必须放到
# if __name__ == '__main__'的子代码中
# 子进程不会再次加载
if __name__ == '__main__':
    p = Process(target=task)
    p.start()
    print('主', current_process().pid)

os.getpid() 查看进程id

# os模块也可以
from multiprocessing import Process, current_process
import time, os

def task():
    print('%s is running 爹是%s' % (os.getpid(), os.getppid()))
    time.sleep(3)
    print('%s is done爹是%s' % (os.getpid(), os.getppid()))

# 开启子进程的操作必须放到
# if __name__ == '__main__'的子代码中
# 子进程不会再次加载
if __name__ == '__main__':
    p = Process(target=task)
    p.start()
    # 谁把主进程创造出来的
    #   用pycharm就是pycharm创造的
    print('主%s爹是%s' % (os.getpid(), os.getppid()))

进程其他方法和属性

from multiprocessing import Process,current_process
import time,os
def task():
    print('%s is running 爹是%s'%(os.getpid(),os.getppid()))
    time.sleep(30)
    print('%s is done爹是%s'%(os.getpid(),os.getppid()))
# 开启子进程的操作必须放到
# if __name__ == '__main__'的子代码中
# 子进程不会再次加载
if __name__ == '__main__':
    p=Process(target=task)
    p.start()
    # 谁把主进程创造出来的
    # 用pycharm就是pycharm创造的
    # 进程的名字
    print(p.name)
    # 杀死子进程
    p.terminate()
    # 需要时间
    time.sleep(0.1)
    #  判断子进程是否存活
    print(p.is_alive())
    print('主%s爹是%s'%(os.getpid(),os.getppid()))

守护进程

本质就是一个"子进程",该"子进程"的生命周期<=被守护进程的生命周期
当被守护的进程执行完了。它也会被杀死

# 主进程运行完了,子进程没有存在的意义
# 皇帝和太监不是同生,但是是同死
from  multiprocessing import Process
import time
def task(name):
    print('%s活着'%name)
    time.sleep(3)
    print('%s正常死亡'%name)
if __name__ == '__main__':
    p1=Process(target=task,args=('老太监',))
    # 声明子进程为守护进程
    p1.daemon = True
    p1.start()
    time.sleep(1)
    print('皇帝正在死亡')

互斥锁

进程之间内存空间互相隔离,怎样实现共享数据
进程之间内存数据不共享,但是共享同一套文件系统,所以访问同一个文件,是没有问题的,
而共享带来的是竞争,竞争带来的结果就是错乱,如何控制,就是加锁处理

'''
抢票
    查票
    购票
互斥锁:
    在程序中进行加锁处理
    必须要释放锁下一个锁才能获取,所以程序在合适的时候必须要有释放锁
所以用文件来处理共享数据
    1.速度慢
    2.必须有互斥锁
'''
import json
import time,random
from multiprocessing import Process,Lock
# 查票
def search(name):
    with open('db.json','rt',encoding='utf-8')as f:
        dic = json.load(f)
    # 模拟查票时间
    time.sleep(1)
    print('%s 查看到余票为 %s'%(name,dic['count']))
# 购票
# 第二个get子进程不会是第一个get子进程修改后count的结果
# 加互斥锁,把这一部分并发变成串行,
# 但是牺牲了效率,保证了数据安全
def get(name):
    with open('db.json','rt',encoding='utf-8')as f:
        dic = json.load(f)
    if dic['count']>0:
        dic['count']-=1
        time.sleep(random.randint(1,3))
        with open('db.json', 'wt', encoding='utf-8')as f:
            json.dump(dic,f)
            print('%s 购票成功'%name)
    else:
        print('%s 查看到没有票了'%name)
def task(name,mutex):
    # 并发
    search(name)
    # 串行
    # 加互斥锁
    mutex.acquire()
    get(name)
    # 释放互斥锁
    mutex.release()
# if __name__ == '__main__':
#     for i in range(10):
#         p=Process(target=task,args=('路人%s'%i,))
#         p.start()
#         #  join只能将进程的任务整体变成串行
#         # 互斥锁可以局部串行
#         p.join()
#         # 数据安全,是指读的时候无所谓,写的(改的)时候必须安全
#         # 写的时候是串行,读的时候并发
# 加锁
if __name__ == '__main__':
    # 主进程加锁
    mutex=Lock()
    for i in range(10):
        # 锁传入子进程
        p=Process(target=task,args=('路人%s'%i,mutex))
        p.start()
        #  join只能将进程的任务整体变成串行
        # 互斥锁可以局部串行
        # p.join()
        # 数据安全,是指读的时候无所谓,写的(改的)时候必须安全
        # 写的时候是串行,读的时候并发

db.json 中只有10张票。如果没有加锁。则可能会出现票呗多卖的情况

进程间通信(IPC机制)

'''
速度快
锁问题解决
ipc机制
    进程彼此之间互相隔离,要实现进程间通信(IPC),
    multiprocessing模块支持两种形式:队列和管道,这两种方式都是使用消息传递的
    共享内存空间
    队列=管道+锁
'''
from  multiprocessing import Queue
# 占用的内存,最好小数据,消息数据,下载地址
# Queue(限制队列里面的个数)
# 先进先出
q=Queue(3)
# 添加
q.put('a')
q.put('b')
q.put({'x':2})
print('篮子满了')
# 队列满了,相当于锁了
# q.put({'x':2})
# 提取
print(q.get())
print(q.get())
print(q.get())
# # 队列为空,等待加入,也会阻塞,相当于锁了
print('队列为空')
print(q.get())

队列被取完了 后面的q.get() 会阻塞直到有新的元素。所以程序不会结束

JoinableQueue 来实现生产消费者

JoinableQueue#task_done()方法当队列里面没有元素会结束线程

'''
小王和小周每人生产10分包子和土豆丝
小戴和小杨一直吃,当队列里面没有食物时。终结进程
'''
import time, random
from multiprocessing import Process, JoinableQueue

def producer(name, food, q):
    for i in range(10):
        res = '%s%s' % (food, i)
        # 模拟生产数据的时间
        time.sleep(random.randint(1, 3))
        q.put(res)
        print('厨师%s生成了%s' % (name, res))

def consumer(name, q):
    while True:
        # 订单都没了还在等,队列里面空了
        res = q.get()
        # 模拟处理数据的时间
        time.sleep(random.randint(1, 3))
        print('吃货%s吃了%s' % (name, res))
        # 1每次完成队列取一次,往q.join() ,取干净了q.join()运行完
        q.task_done()

# 多个生产者和消费者
if __name__ == '__main__':
    q = JoinableQueue()
    # 生产者
    p1 = Process(target=producer, args=('小王', '包子', q))
    p3 = Process(target=producer, args=('小周', '土豆丝', q))
    # 消费者
    c1 = Process(target=consumer, args=('小戴', q))
    c2 = Process(target=consumer, args=('小杨', q))
    # #3.守护进程的作用: 主进程死了,消费者子进程也跟着死
    #     #把消费者变成守护进程
    c1.daemon = True
    c2.daemon = True
    p1.start()
    p3.start()
    c1.start()
    c2.start()
    p1.join()
    p3.join()
    # 2消费者task_done给q.join()发信号
    q.join()
    print('主')
    # 生产者运行完?1,2
    # 消费者运行完?1,2

当队列为空时,不会傻傻等待而是结束进程

总结

本篇文章就到这里了,希望能够给你带来帮助,也希望您能够多多关注我们的更多内容!

(0)

相关推荐

  • Python 多进程原理及实现

    1 进程的基本概念 什么是进程? ​ 进程就是一个程序在一个数据集上的一次动态执行过程.进程一般由程序.数据集.进程控制块三部分组成.我们编写的程序用来描述进程要完成哪些功能以及如何完成:数据集则是程序在执行过程中所需要使用的资源:进程控制块用来记录进程的外部特征,描述进程的执行变化过程,系统可以利用它来控制和管理进程,它是系统感知进程存在的唯一标志. 进程的生命周期:创建(New).就绪(Runnable).运行(Running).阻塞(Block).销毁(Destroy) 进程的状态(分类)

  • python 实现多进程日志轮转ConcurrentLogHandler

    记录日志是我们程序中必不可少的一个功能,但是日志文件如果没有合理的管理,时间长了几百兆的日志文件就很难分析了(都不想打开看),但是又不可能经常手动去管理它 日志轮转:根据时间或者文件大小控制日志的文件个数,不用我们手动管理 python中logging模块内置的有几个支持日志轮转的handler 常用的有TimedRotatingFileHandler根据时间轮转 RotatingFileHandler根据文件大小轮转 但是内置的这些handler是多线程安全的,而不支持多进程(可以修改源码加锁

  • Python多线程与多进程相关知识总结

    一.什么是进程 进程是执行中的程序,是资源分配的最小单位:操作系统以进程为单位分配存储空间,进程拥有独立地址空间.内存.数据栈等 操作系统管理所有进程的执行,分配资源 可以通过fork或 spawn的方式派生新进程,新进程也有自己独立的内存空间 进程间通信方式(IPC,Inter-Process Communication)共享信息,实现数据共享,包括管道.信号.套接字.共享内存区等. 二.什么是线程 线程是CPU调度的的最小单位 一个进程可以有多个线程 同进程下执行,并共享相同的上下文 线程间

  • python实现多进程并发控制Semaphore与互斥锁LOCK

    一.了解锁 应用场景举例描述: Lock 互斥锁:举例说明–有三个同事同时需要上厕所,但是只有一间厕所,将同事比作进程,多个进程并打抢占一个厕所,我们要保证顺序优先, 一个个来,那么就必须串行,先到先得,有人使用了,就锁住,结束后剩余的人继续争抢 1.利用Lock来处理 模拟三个同事抢占厕所 from multiprocessing import Process from multiprocessing import Lock import time import random def task

  • Python多进程的使用详情

    目录 一.进程的创建 1.一些常用方法介绍 二.进程池的使用 三.多进程和多线程的优缺点对比 一.进程的创建 Python的multiprocessing模块提供了Process类,该类可用来在各平台下创建新进程.其构造函数是: __init__(self, group=None, target=None, name=None, args=(), kwargs={}) 其中,各个参数的含义如下: group: 该参数未实现,不需要传参 target:为新建进程指定执行任务,也就是指定一个函数 a

  • python 多进程和多线程使用详解

    进程和线程 进程是系统进行资源分配的最小单位,线程是系统进行调度执行的最小单位: 一个应用程序至少包含一个进程,一个进程至少包含一个线程: 每个进程在执行过程中拥有独立的内存空间,而一个进程中的线程之间是共享该进程的内存空间的: 计算机的核心是CPU,它承担了所有的计算任务.它就像一座工厂,时刻在运行. 假定工厂的电力有限,一次只能供给一个车间使用.也就是说,一个车间开工的时候,其他车间都必须停工.背后的含义就是,单个CPU一次只能运行一个任务.编者注: 多核的CPU就像有了多个发电厂,使多工厂

  • python多进程基础详解

    目录 进程 开启一个进程 JOIN方法 进程之间空间隔离 进程的常用方法 current_process 查看pid(进程id) os.getpid() 查看进程id 进程其他方法和属性 守护进程 互斥锁 进程间通信(IPC机制) JoinableQueue 来实现生产消费者 总结 进程 什么是进程 进程指的是一个程序的运行过程,或者说一个正在执行的程序 所以说进程一种虚拟的概念,该虚拟概念起源操作系统 一个CPU 同一时刻只能执行一件事 开启一个进程 from multiprocessing

  • python多线程和多进程关系详解

    关于多线程的大概讲解: 在Python的标准库中给出了2个模块:_thread和threading,_thread是低级模块不支持守护线程,当主线程退出了时,全部子线程都会被强制退出了.而threading是高级模块,用作对_thread进行了封装支持守护线程.在大部分状况下人们只需要采用threading这个高级模块即可. 关于多进程的大概讲解: 多进程是multiprocessing模块给出远程与本地的并发,在一个multiprocessing库的采用场景下,全部的子进程全是由一个父进程运行

  • Python基础详解之描述符

    一.描述符定义 描述符是一种类,我们把实现了__get__().__set__()和__delete__()中的其中任意一种方法的类称之为描述符. 描述符的作用是用来代理一个类的属性,需要注意的是描述符不能定义在被使用类的构造函数中,只能定义为类的属性,它只属于类的,不属于实例,我们可以通过查看实例和类的字典来确认这一点. 描述符是实现大部分Python类特性中最底层的数据结构的实现手段,我们常使用的@classmethod.@staticmethd.@property.甚至是__slots__

  • Python基础详解之邮件处理

    一.发送电子邮件 Python标准库提供了smtplib,用于实现SMTP协议发送邮件.标准库还提供email模块帮助我们构建邮件格式.SMTP(Simple Mail Transfer Protocol,即简单邮件传输协议),是一组有源地址到目的地址传送邮件的规则,用来控制信件的中转方式. 获取QQ邮箱密码(授权码) 二.发送纯文本格式的邮件 import smtplib from email.mime.text import MIMEText from email.header import

  • Python基础详解之列表复制

    一.前言 Python中列表的复制分为几种情况: 直接赋值 浅复制 深复制 下面通过实例分析一下这几种情况的区别. 二.直接赋值 a = [11, 22, 33] b = a print(id(a), id(b)) b[0]=1 print(a,b) 输出结果为如下所示,发现内存地址没有发生变化,b只是a的引用,通过b更改列表的值时,a同时做修改. 三.用切片赋值 a = [11, 22, 33] b = a[:] print(id(a), id(b)) b[0]=1 print(a,b) 输出

  • python基础详解之if循环语句

    前言 还记得这个九九乘法表吗,这次课后相信你可以用代码给你的小弟弟妹妹们变出这份"葵花宝典". 循环 如果要把循环翻译成机器语言,那他对应的可以是 for-in- ,循环就像是一个可爱的搬砖人,简单的一条语句帮我们解决了很多的重复劳动. 上面的语句实现了计算15,25,35,45,55的功能,i就像是一个彩票,不过他有自己的性格,这是个热爱平等的彩票,他会依次访问[ ]里的值,当他访问1时i就为1,此时将会执行print(15),接下来访问2时i就为2,继续执行乘法工作,直到[]里每一

  • python 类的基础详解与应用

    目录 类的定义 类对象 变量 类变量 局部变量 实例变量 私有变量 类的方法 特殊方法 继承 单继承 多继承 类的定义 # class是定义类的关键字,ClassName为类的名称 class ClassName: # 在这里写其他内容 pass class ClassName(object): # 在这里写其他内容 pass 这是一个最简单的类定义,在python3后类定义一般都会继承object类,不过不继承也没有多大的问题. 类对象 类对象也称实例 # 这就是创建了一个类对象(实例),a是

  • Python+Selenium自动化环境搭建与操作基础详解

    目录 一.环境搭建 1.python安装 2.pycharm下载安装 3.selenium下载安装 4.浏览器驱动下载安装 二.Selenium简介 (1)SeleniumIDE (2)SeleniumRC (3)SeleniumWebDriver (4)SeleniumGrid 三.常用方法 1.浏览器操作 2.如何获取页面元素 3.查找定位页面元素的方法 4.操作方法 5.下拉框操作 6.WINDOS弹窗 7.iframe内嵌页面处理 8.上传文件 9.切换页面 10.截图 11.等待时间

  • windows上安装Anaconda和python的教程详解

    一提到数字图像处理编程,可能大多数人就会想到matlab,但matlab也有自身的缺点: 1.不开源,价格贵 2.软件容量大.一般3G以上,高版本甚至达5G以上. 3.只能做研究,不易转化成软件. 因此,我们这里使用Python这个脚本语言来进行数字图像处理. 要使用Python,必须先安装python,一般是2.7版本以上,不管是在windows系统,还是Linux系统,安装都是非常简单的. 要使用python进行各种开发和科学计算,还需要安装对应的包.这和matlab非常相似,只是matla

  • python 全文检索引擎详解

    python 全文检索引擎详解 最近一直在探索着如何用Python实现像百度那样的关键词检索功能.说起关键词检索,我们会不由自主地联想到正则表达式.正则表达式是所有检索的基础,python中有个re类,是专门用于正则匹配.然而,光光是正则表达式是不能很好实现检索功能的. python有一个whoosh包,是专门用于全文搜索引擎. whoosh在国内使用的比较少,而它的性能还没有sphinx/coreseek成熟,不过不同于前者,这是一个纯python库,对python的爱好者更为方便使用.具体的

随机推荐