栏目分类:
子分类:
返回
文库吧用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
文库吧 > IT > 软件开发 > 后端开发 > Python

Day38——进程的创建方法,join方法,进程对象

Python 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Day38——进程的创建方法,join方法,进程对象

文章目录
  • 创建进程的多方法
    • multiprocess模块
  • join方法
  • 进程间数据默认隔离
  • 进程间通信(IPC机制)
  • 生产者消费者模型
  • 进程相关方法
  • 守护进程
  • 僵尸进程与孤儿进程
  • 互斥锁
  • 今日作业

创建进程的多方法
  • 本质:

    但凡是硬件,都需要有操作系统去管理,只要有操作系统,就有进程的概念,就需要有创建进程的方式,一些操作系统只为一个应用程序设计,比如扫地机器人,一旦启动,所有的进程都已经存在

multiprocess模块

导入模块:from multiprocessing import Process

  • multiprocess不是一个模块是一个操作、管理进程的包。这个包几乎包含了和进程有关的所有子模块。大致分为四个部分:创建进程部分,进程同步部分,进程池部分,进程之间数据共享。

  • Process类介绍

    Process(group,target,name,args,kwargs)
    强调:
    1.需要使用关键子的方式来指定参数
    2.args指定的为传给target函数的位置参数,是一个元组形式,必须有逗号
    参数介绍:
    1.group参数未使用,值始终未None
    2.target表示调用对象,即子进程要执行的任务
    3.args表示调用对象的位置参数元组,args=(1,2,‘y’,)
    4.kwargs表示调用对象的字典,kwargs={‘name’:‘kkk’}
    5.name为子进程的名称

  • Process类创建进程的两种方式

    方法一

    from multiprocessing import Process
    import time
    
    
    def task(name):
        print(f'{name}正在运行')
        time.sleep(3)
        print(f'{name}运行结束')
    
    
    if __name__ == '__main__':
        p = Process(target=task, args=('jason',))  # 创建一个进程对象
        p.start()  # 告诉操作系统创建一个进程(异步操作)
        # task('jason')  # 普通的函数调用是同步操作
        print('主进程')
    

    方法二

    import time
    class MyProcess(Process):
        def __init__(self, name):
            super().__init__()
            self.name = name
    
        def run(self):
            print(f'{self.name}正在运行')
            time.sleep(5)
            print(f'{self.name}运行结束')
    
    
    if __name__ == '__main__':
        obj = MyProcess('jason')
        obj.start()
        print('主进程')
    

注意:

强调:在Windows操作系统中由于没有fork(linux操作系统中创建进程的机制),在创建子进程的时候会自动 import 启动它的这个文件,而在 import 的时候又执行了整个文件。因此如果将process()直接写在文件中就会无限递归创建子进程报错。所以必须把创建子进程的部分使用if __name__ == '__main__' 判断保护起来,import 的时候 ,就不会递归运行了。

join方法
  • 作用

    在进程中可以阻塞主进程的执行, 直到等待子线程全部完成之后, 才继续运行主进程后面的代码
    其实就是实现进程同步

  • 举例说明

'''不加join方法'''
from multiprocessing import Process
import time


def task(name):
    print(f'{name}正在运行')
    time.sleep(3)
    print(f'{name}运行结束')


if __name__ == '__main__':
    p = Process(target=task, args=('jason',))  # 创建一个进程对象
    p.start()  # 告诉操作系统创建一个进程(异步操作)
    print('主进程')

'''
输出顺序:
主进程
jason正在运行
jason运行结束
'''
'''使用了join的方法'''
from multiprocessing import Process
import time


def task(name):
    print(f'{name}正在运行')
    time.sleep(3)
    print(f'{name}运行结束')


if __name__ == '__main__':
    p = Process(target=task, args=('jason',))  # 创建一个进程对象
    p.start()  # 告诉操作系统创建一个进程(异步操作)
    p.join()  # 先执行完子线程,再往下执行
    print('主进程')

'''
输出顺序:
jason正在运行
jason运行结束
主进程
'''

使用join方法的时候,一定要看准join的执行位置 以及多任务情况下等待的目标

进程间数据默认隔离

内存可以看成是有很多个小隔间组成的 彼此不干扰
在同一台计算机上的多个应用程序在内存中是相互隔离的(物理级别隔离)
如果真的想交互 需要借助于管道或者队列

  • 代码验证

判断主进程中money的值是否改变,没有改变则说明父进程与子进程之间数据隔离

from multiprocessing import Process


money = 100


def task():
    global money
    money = 666
    print('子进程打印的money', money)  # 子进程打印的money 666


if __name__ == '__main__':
    p = Process(target=task)
    p.start()
    p.join()
    print('父进程打印的money', money)  # 父进程打印的money 100
进程间通信(IPC机制)
  • 思考

    1.什么是队列?

    先进先出,后进后出
    

    创建队列:q = Queue(3) (括号内指定队列可以容纳的数据个数) 默认:2147483647
    队列添加数据:q.put(数据)
    判断队列是否已经存满:q.full() (返回的是True,False)
    队列中取数据:q.get() (没有值的时候,不会报错,会一直处于阻塞状态等待数据值的传入)
    队列中取数据:q.get_nowait() (没有值的时候,会直接报错)
    判断队列是否已经空了:q.empty()

注意:上述方法在多进程下不能准确使用(失效)!!!

  • IPC机制

    1.主进程与子进程通信
    2.子进程与子进程通信
    
  • 代码实操

    from multiprocessing import Process, Queue
    import time
    
    
    def task(q):
        print(f'{q.get()}你好呀')
        time.sleep(3)
        print(f'我{q.get()}很好')
    
    
    def run(q):
        q.put('lzq')
        q.put('gsy')
    
    
    if __name__ == '__main__':
        q = Queue(2)
        p = Process(target=run, args=(q,))
        p1 = Process(target=task, args=(q,))
        p.start()
        p1.start()
        p1.join()
        print('主进程')
    
    '''
    输出顺序:
    lzq你好呀
    我gsy很好
    主进程
    '''
    
生产者消费者模型
生产者
	产生数据
消费者
	处理数据

举例说明:

生产者:获取网页数据的代码(函数)
	爬取
消费者:从网页数据中筛选出符合条件的数据(函数)
	筛选

完整的生产者消费者模型至少有三个部分

生产者
消息队列/数据库
消费者
进程相关方法
  • 常见的属性和方法

    pid:获取子进程id (ppid:获取父进程的id)
    
    name:获取子进程name属性
    
    terminate:杀死子进程
    
    is_alive:查看子进程是否还活着
    
  • PID的含义

    在内存中开启多个进程,操作系统利用PID区分这些进程,每个进程都有一个唯一PID表示

  • PID获取方法

    1.终端查看所有pid tasklist
    2.指定具体的PID tasklist | findstr python
    3.代码查看pid os 模块
    4.current_process函数()
    from multiprocessing import Process, current_process
    current_process().pid

守护进程

守护进程(daemon)是一类在后台运行的特殊进程,用于执行特定的系统任务。很多守护进程在系统引导的时候启动,并且一直运行直到系统关闭。另一些只在需要的时候才启动,完成任务后就自动结束。

1.如何理解守护?

伴随着守护对象的存活而存活 死亡而死亡

2.代码实操

from multiprocessing import Process
import time


def task(name):
    print('大内总管:%s存活' % name)
    time.sleep(3)
    print('大内总管:%s嗝屁' % name)


if __name__ == '__main__':
    p = Process(target=task, args=('基佬',))
    p.daemon = True  # 将子进程设置为守护进程:主进程代码结束 子进程立刻结束
    p.start()
    print('天子Jason寿终正寝!!!')

注意:p.daemon = True 必须在start之前执行

僵尸进程与孤儿进程
  • 进程运行了解

每个进程退出时,内核释放应该进程所有的资源,但是还会保留一部分的信息,如:进程号,进程状态,运行时间.直到主进程利用这个waitepid()方法,才能够完全释放,回收子进程的资源

僵尸进程
	进程已经运行结束 但是相关的资源并没有完全清空
	需要父进程参与回收
孤儿进程
	父进程意外死亡 子进程正常运行 该子进程就称之为孤儿进程
	孤儿进程也不是没有人管 操作系统会自动分配福利院接收

僵尸进程的劣势

僵尸进程的资源无法被释放,长期占用.内存压力增大.当新的程序来处理时,则会因为资源不足而导致运行失败.

互斥锁
  • 模拟抢票
from multiprocessing import Process
import time
import json
import random


# 查票
def search(name):
    with open(r'data.json', 'r', encoding='utf8') as f:
        data = json.load(f)
    print('%s在查票 当前余票为:%s' % (name, data.get('ticket_num')))


# 买票
def buy(name):
    # 再次确认票
    with open(r'data.json', 'r', encoding='utf8') as f:
        data = json.load(f)
    # 模拟网络延迟
    time.sleep(random.randint(1, 3))
    # 判断是否有票 有就买
    if data.get('ticket_num') > 0:
        data['ticket_num'] -= 1
        with open(r'data.json', 'w', encoding='utf8') as f:
            json.dump(data, f)
        print('%s买票成功' % name)
    else:
        print('%s很倒霉 没有抢到票' % name)


def run(name):
    search(name)
    buy(name)


if __name__ == '__main__':
    for i in range(10):
        p = Process(target=run, args=('用户%s'%i, ))
        p.start()

但是这样出现有很大的问题

今日作业

1.尝试将TCP服务端制作成并发效果
客户端服务端全部设置成自动发消息自动回消息
eg: 客户端发hello 服务端直接转大写回HELLO

服务端:

import socket
from multiprocessing import Process


def run():
    server = socket.socket()
    server.bind(('127.0.0.1', 8080))
    server.listen(5)
    return server


def server1(sort):
    data = sort.recv(1024)
    sort.send(('你的信息:%s' % data.upper()).encode('utf8'))
    print(data.decode('utf8'))


if __name__ == '__main__':
    server = run()
    number = 0
    while number < 6:
        sort, address = server.accept()  # 循环等待客人的到来
        p = Process(target=server1, args=(sort,))
        p.start()
        number += 1

客户端

import socket


while True:
    client = socket.socket()
    client.connect(('127.0.0.1', 8080))
    client.send('hello'.encode('utf8'))
    print(client.recv(1024).decode('utf8'))
转载请注明:文章转载自 www.wk8.com.cn
本文地址:https://www.wk8.com.cn/it/1037409.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 wk8.com.cn

ICP备案号:晋ICP备2021003244-6号