python高级技术(进程二)

这篇具有很好参考价值的文章主要介绍了python高级技术(进程二)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

一 进程对象及其他方法

'''
一台计算机上面运行着很多进程,那么计算机是如何区分并管理这些进程服务端的呢?
计算机会给每一个运行的进程分配一个PID号
如何查看
windows电脑
进入cmd输入tasklist即可查看
tasklist|findstr PID查看具体的进程
linux电脑
进入终端之后输入ps aux
ps aux|grep PID查看具体的进程
'''
from multiprocessing import Process, current_process
import time
import os


def task():
    print('{} is running'.format(current_process().pid))
    print('{} is running'.format(os.getpid()))
    print('{} 是子进程的主进程号'.format(os.getppid()))
    time.sleep(5)


if __name__ == '__main__':
    p = Process(target=task)
    p.start()
    # p.terminate()  # 杀死当前进程
    # 是告诉操作系统帮你去杀死当前进程 但是需要一定的时间 而代码的运行速度极快,加上time.sleep,打印结果为True
    # time.sleep(0.001)
    print(p.is_alive())  # 判断当前进程是否存活
    '''
    一般情况下我们会默认将
    存储布尔值的变量名 
    和返回的结果是布尔值的方法名
    都起成以is_开头
    '''
    print('', current_process().pid)
    print('主进程的父进程号', os.getpid())
    
'''
rue
主 6308
主进程的父进程号 6308
16144 is running
16144 is running
6308 是子进程的主进程号
'''
current_process().pid和os.getpid()都是获取当前进程的进程号,
os.getppid()获取当前进程的父进程
p.terminate() 杀死当前进程
p.is_alive()判断当前进程是否存活

二 僵尸进程与孤儿进程(了解)

1、僵尸进程
死了但是没有死透
当你开设了子进程之后,该进程死后不会立刻释放占用的进程号
因为我要让父进程能够查看到它开设的子进程的一些基本信息 占用的pid号 运行时间
所有的进程都会步入僵尸进程
父进程不死并且在无限制的创建子进程并且子进程也不结束
回收子进程占用的pid号
父进程等待子进程运行结束
父进程调用join方法
2、孤儿进程
子进程存活,父进程意味死亡
操作系统会开设一个“儿童福利院”专门管理孤儿进程回收相关资源

三 守护进程

会随着主进程的结束而结束。

主进程创建守护进程

  其一:守护进程会在主进程代码执行结束后就终止

  其二:守护进程内无法再开启子进程,否则抛出异常:AssertionError: daemonic processes are not allowed to have children

注意:进程之间是互相独立的,主进程代码运行结束,守护进程随即终止

from multiprocessing import Process
import time


def task(name):
    print('{}正在活着'.format(name))
    time.sleep(3)
    print('{}正在死亡'.format(name))


if __name__ == '__main__':
    p = Process(target=task, args=('xiaobao',))
    p.daemon = True  # 将进程p设置成守护进程 这一句一定要放在start方法上面才有效否则会直接报错
    p.start()
    print('haha')

'''
haha
'''

四 互斥锁

多个进程操作同一份数据的时候,会出现数据错乱的问题
针对上述问题,解决方式就是加锁处理
将并发变成串行,牺牲效率但是保证了数据的安全
from multiprocessing import Process, Lock
import json
import time
import random


# 查票
def search(i):
    # 文件操作读取票数
    with open('data', 'r', encoding='utf-8') as f:
        dic = json.load(f)  # 操作文件用load,具体对象数据用loads
    print('用户名{}查询余票{}'.format(i, dic.get('ticket_num')))
    # 字典取值不要用[]的形式,如果没有,会报错,推荐使用get,写代码尽量避免报错。


# 买票 1.先查 2.再买
def buy(i):
    # 先查票
    with open('data', 'r', encoding='utf-8') as f:
        dic = json.load(f)

    # 模拟网络延迟
    time.sleep(random.randint(1, 3))
    # 判断当前是否有票
    if dic.get('ticket_num') > 0:
        # 修改数据库 买票
        dic['ticket_num'] -= 1
        # 写入数据库
        with open('data', 'w', encoding='utf-8') as f:
            json.dump(dic, f)
        print('用户{}买票成功'.format(i))
    else:
        print('用户{}买票失败'.format(i))


# 整合上面两个函数
def run(i, mutex):
    search(i)
    # 给买票环节加锁处理
    # 抢锁
    mutex.acquire()
    buy(i)
    # 释放锁
    mutex.release()


if __name__ == '__main__':
    # 在主进程中生成一把锁 让所有的子进程抢 谁先抢到谁先买票
    mutex = Lock()
    for i in range(1, 11):
        p = Process(target=run, args=(i, mutex))
        p.start()

模拟抢票,一个用户对应一个进程,余票剩余1张,不加锁的情况下,因是并发,10个用户

显示都够买成功了1张,实际情况只能有1个用户购买成功,所以加锁,10个用户抢锁

,锁先抢到,谁先运行,让并发效果变成了串行效果,牺牲了效率,保证了数据安全

'''
扩展 行锁 表锁
注意:
1、锁不要轻易的使用,容易造成死锁现象(我们写代码一般不会用到,都是内部封装好的)
2、锁只在处理数据的部分来保证数据安全(只在争抢数据的环节加锁处理即可)
'''

五 进程间通信

队列:先进先出(扶手电梯)
堆栈:先进后出(箱子里叠衣服)

管道:subprocess
stdin stdout stderr
队列:管道+锁

python高级技术(进程二)
from multiprocessing import Queue

# 创建一个队列
q = Queue(5)  # 括号内可以传数字 表示生成的队列最大可以同时存放的数据量
q.put(111)
q.put(222)
q.put(333)
print(q.full())  # 判断当前队列是否满了
print(q.empty())  # 判断当前队列是否空了
q.put(444)
q.put(555)
# q.put(666) # 当队列数据放满了之后 如果还有数据要放程序会阻塞 直到有位置让出来

'''
存取数据 存是为了更好的取
千方百计的存、简单快捷的取
'''
# 去队列中取数据
v1 = q.get()
v2 = q.get()
v3 = q.get()
v4 = q.get()
v5 = q.get()
# v6 = q.get()    # 队列中如果已经没有数据的话 get方法会原地阻塞
try:
    v6 = q.get(timeout=3)
    print(v6)
except Exception as e:
    print('已经被取完了')
print(v1)

'''
q.full()
q.empty()
q.get_nowait()
在多进程的情况下是不精准
'''

put 当队列数据放满了之后 如果还有数据要放程序会阻塞 直到有位置让出来

get  队列中如果已经没有数据的话 get方法会原地阻塞

IPC机制

from multiprocessing import Process, Queue

'''
研究思路
    1、主进程跟子进程借助于队列通信
    2、子进程跟子进程借助于队列通信
'''


def producer(q):
    q.put('zd')
    print('hello llx')


def consumer(q):
    print(q.get())


if __name__ == '__main__':
    q = Queue()
    p = Process(target=producer, args=(q,))
    p1 = Process(target=consumer, args=(q,))
    p.start()
    p1.start()

'''
hello llx
zd
'''

六 生产者消费者模型

生产者:生产/制造东西的
消费者:消费/处理东西的
该模型除了上述两个之外还需要一个媒介
生产者和消费者之间不是直接做交互的,而是借助于媒介做交互
生产者+消费队列+消费者

生产者消费者模式是通过一个容器来解决生产者和消费者的强耦合问题。
生产者和消费者彼此之间不直接通讯,而通过阻塞队列来进行通讯,
所以生产者生产完数据之后不用等待消费者处理,直接扔给阻塞队列,
消费者不找生产者要数据,而是直接从阻塞队列里取,阻塞队列就相当于一个缓冲区,
平衡了生产者和消费者的处理能力。
from multiprocessing import Process, Queue
import time
import random


def producer(name, food, q):
    for i in range(10):
        data = '{}生产了{}{}'.format(name, i, food)
        # 模拟延迟
        time.sleep(random.randint(1, 3))
        print(data)
        # 将数据放入队列中
        q.put(data)


def consumer(name, q):
    # 消费者胃口很大 光盘行动
    while True:
        food = q.get()
        if food is None:
            break
        time.sleep(random.randint(1, 3))
        print('{}吃了{}'.format(name, food))


if __name__ == '__main__':
    q = Queue()
    p1 = Process(target=producer, args=('大厨lq', '包子', q))
    p2 = Process(target=producer, args=('大厨zd', '油条', q))
    c1 = Process(target=consumer, args=('吃货xiao', q))
    c2 = Process(target=consumer, args=('吃货xiaoxiaobao', q))
    p1.start()
    p2.start()
    c1.start()
    c2.start()
    p1.join()
    p2.join()
    # 等待生产者生产完毕之后 往队列中添加特定的结束符号
    q.put(None)  # 肯定在所有生产者生产的数据的末尾,有几个消费者,就要有几个put(None)
    q.put(None) # 主进程与子进程的通信

解决生产者生产完毕后,有几个消费者就需要向几个消费者添加几个put(None)的结束标志的问题,

使用JoinableQueue模块

from multiprocessing import Process, JoinableQueue
import time
import random


def producer(name, food, q):
    for i in range(10):
        data = '{}生产了{}{}'.format(name, i, food)
        # 模拟延迟
        time.sleep(random.randint(1, 3))
        print(data)
        # 将数据放入队列中
        q.put(data)


def consumer(name, q):
    # 消费者胃口很大 光盘行动
    while True:
        food = q.get()
        time.sleep(random.randint(1, 3))
        print('{}吃了{}'.format(name, food))
        q.task_done()  # 告诉队列你已经从里面取出了一个数据并且处理完毕了


if __name__ == '__main__':
    q = JoinableQueue()
    p1 = Process(target=producer, args=('大厨lq', '包子', q))
    p2 = Process(target=producer, args=('大厨zd', '油条', q))
    c1 = Process(target=consumer, args=('吃货xiao', q))
    c2 = Process(target=consumer, args=('吃货cyz', q))
    p1.start()
    p2.start()
    # 将消费者设置成守护进程
    c1.daemon = True
    c2.daemon = True
    c1.start()
    c2.start()

    p1.join()
    p2.join()
    q.join()  # 等待队列中所有的数据被取完再执行往下执行代码
    '''
    JoinableQueue 每当你往队列中存入数据的时候 内部会有一个计数器+1
    每当你调用task_done的时候 计数器-1
    q.join() 当计数器为0的时候 才往后运行
    #主进程等--->p1,p2等---->c1,c2
    #p1,p2结束了,证明c1,c2肯定全都收完了p1,p2发到队列的数据
    #因而c1,c2也没有存在的价值了,不需要继续阻塞在进程中影响主进程了。应该随着主进程的结束而结束,所以设置成守护进程就可以了。
    '''

 文章来源地址https://www.toymoban.com/news/detail-441347.html

到了这里,关于python高级技术(进程二)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 高级路由技术案例

    1、静态ECMP和浮动静态路由配置实验: 2、浮动静态路由配置 案例内容与目标: 1、如何在路由器上配置静态ECMP 2浮动静态路由配置 案例组网图: 案例设备和器材: 两台路由器 两台PC 案例主要过程: 步骤一:建立物理连接 步骤二:ip地址配置: PCA配置: PCB: RTA: RTB: 步

    2024年02月02日
    浏览(39)
  • 5 种高级 NodeJS 技术

    作为开发人员,我们都致力于打造高效、健壮且易于理解、修改和扩展的代码库。通过采用最佳实践和探索先进技术,我们可以释放 NodeJS 的真正潜力并显着提高应用程序的质量。在这篇文章中,我们将重点介绍 NodeJS 的五种高级技术。所以,系好安全带,我们要开车了,准备

    2024年02月09日
    浏览(32)
  • Java高级技术:单元测试、反射、注解

    目录 单元测试 单元测试概述 单元测试快速入门 单元测试常用注解 反射 反射概述 反射获取类对象 反射获取构造器对象 反射获取成员变量对象 反射获取方法对象 反射的作用-绕过编译阶段为集合添加数据 反射的作用-通用框架的底层原理 注解 注解概述 自定义注解 元注解

    2024年01月16日
    浏览(51)
  • java 高级面试题整理(薄弱技术)

    session 1.什么是session Session是另一种记录客户状态的机制,不同的是Cookie保存在客户端浏览器中,而Session保存在服务器上。客户端浏览器访问服务器的时候,服务器把客户端信息以某种形式记录在服务器上。这就是Session。客户端浏览器再次访问时只需要从该Session中查找该客户

    2024年02月11日
    浏览(48)
  • GaussDB技术解读系列之高级压缩

    本文作者 华为云数据库GaussDB首席架构师 冯柯 数据压缩与关系数据库的结合,早已不是一个新鲜的话题,当前我们已经看到了各种各样数据库压缩的产品和解决方案。对于GaussDB来说,在今天引入数据压缩,究竟能够给客户带来什么不一样的价值,是过去一段时间我们一直在

    2024年02月15日
    浏览(53)
  • Java高级技术 单元测试(JUnit4)

    所谓单元测试,就是针对最小的功能单元,编写测试代码对其进行正确性测试。 我们之前一直使用的测试便是通过main方法来实现,但在main方法中写测试代码有如下的几个问题存在: 只能在main方法编写测试代码,去调用其他方法进行测试。 无法实现自动化测试,一个方法测

    2024年02月03日
    浏览(51)
  • 【笔记】Helm-3 主题-9 Helm高级技术

    Helm高级技术 这部分解释说明了使用Helm的各种高级特性和技术。这部分旨在为Helm的高级用户提供高度自定义和操作chart及发布的信息。每个高级特性都会有它自己的权衡利弊, 因此每个使用它们的都要有Helm的深度知识并小心使用。或者换言之,谨记 Peter Parker 原则 https://en

    2024年01月21日
    浏览(37)
  • JAVA高级技术-输入、输出系列-文件的天下大势

    回城传送–》《JAVA筑基100例》 题目:做一个合并多个文本文件的工具。 创建一个类:TextFileConcatenation 使用TextFileConcatenation继承JFrame构建窗体 读取文本文件时,用的是BufferedReader类的readLine()方法读入一行数据。 将选择的多个文本文件合并到d://concatenation.txt 启动: 合并前:

    2024年02月16日
    浏览(48)
  • 数据可视化高级技术Echarts(堆叠柱状图)

    目录 一.如何实现 二.代码展示 1.stack名称相同(直接堆叠) 2. stack名称不相同(相同的堆叠,不同的新生成一列) 数据堆叠,同个类目轴上系列配置相同的  stack  值可以堆叠放置。即在series中将设置stack即可。其他设置与普通柱状图相同, 参考文章: 数据可视化高级技术

    2024年04月10日
    浏览(47)
  • KVM 虚拟化技术高级特性详解

    KVM高级功能包括半虚拟化驱动、VT-d、SR-IOV、热插拔、动态迁移、KSM、AVX、cgroups、从物理机或虚拟机中迁移到KVM,以及QEMU监控器和qemu-kvm命令行的各种选项的使用。 1、半虚拟化驱动 1. virtio概述 KVM是必须使用硬件虚拟化辅助技术(如Intel VT-x、AMD-V)的Hypervisor,在CPU运行效率方

    2024年01月23日
    浏览(42)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包