python学习笔记(十七)进程使用

python学习笔记(十六)进程使用
进程使用

进程简介

什么是进程(任务)?
在计算机中,一个进程就是一个任务,其实就是运行着的程序。
在操作系统中,进程就是程序执行和资源分配的基本单元。

单核CPU实现多任务
将CPU的时间快速的切换和分配到不同的任务上
若频率足够高,切换足够快,人的感官就无法感知

多核CPU实现多任务
如果任务数量不超过CPU数量,完全可以一个核心做一件事
在操作系统中几乎是不可能,通常任务数量都远远大于CPU数量
同样可以采用轮流分配的方式实现多任务,只是同事干活的’人’是多个罢了
为什么使用多进程?
在一个程序中,若出现耗时操作,程序就会出现阻塞(假死),为了解决这种问题可以采用多进程进行解决。如:主进程负责管理工作,子进程负责做耗时操作。

进程管理

简单示例:

import os
import multiprocessing
import time

def do_something(*args, **kwargs):
    print('子进程开始')
    # 获取当前进程
    current_process = multiprocessing.current_process()
    print(current_process.pid, current_process.name)
    # 获取当前进程及父进程ID
    print(os.getpid(), os.getppid())
    print('args:', args)
    print('kwargs:', kwargs)
    time.sleep(5)
    print('子进程结束')
    
# 启动子进程后,系统会拷贝当前代码并加载执行
# 创建并启动子进程操作将无限循环进行下去
# 放在下面的结构中可以解决这个问题
if __name__ == '__main__':
    print('主进程开始')
    # 获取当前进程号
    print(os.getpid())
    # 获取当前进程
    current_process = multiprocessing.current_process()
    print('进程ID:', current_process.pid)
    print('进程名称:', current_process.name)

    # 创建进程
    # target:指定进程任务,其实就是一个函数
    # name:指定进程名称
    # args:传递给进程函数的位置参数,是一个元组
    # kwargs:传递给进程函数的关键字参数,是一个字典
    p = multiprocessing.Process(target=do_something, args=(1, 2, 3), kwargs={'age': 18},name='LoopProcess')

    # 设置子进程随主进程结束而结束,默认为False
    p.daemon = True

    # 启动进程
    p.start()

    # 等待子进程结束
    # p.join()
    time.sleep(1)

    # 手动结束子进程
    p.terminate()

    print('主进程结束')    

进程锁:限制资源只能被一个进程使用

import multiprocessing
import time
from random import random

def loop(lock):
    # 获取锁
    lock.acquire()

    current_process = multiprocessing.current_process()
    print(current_process.name, '开始')
    time.sleep(random() * 5)
    print(current_process.name, '结束')
    # 释放锁
    lock.release()   
    
if __name__ == '__main__':
    # 创建一个进程锁
    lock = multiprocessing.Lock()

    lt = []
    for i in range(1, 6):
        p = multiprocessing.Process(target=loop, args=(lock,), name='子进程'+str(i))
        lt.append(p)
        p.start()

	for p in lt:
		p.join()
 # 为什么在调用子进程的时候是随机的而不是按照生成的顺序???

信号量:限制某个资源最多可以被多少个进程同时使用

import multiprocessing
import random
import time

def run(name, se):
    # 获取信号量
    se.acquire()
    print(name, '进程开始')
    time.sleep(random.random()*3)
    print(name, '进程结束')
    # 释放信号量
    se.release()     
 
if __name__ == '__main__':
    # 创建一个信号量对象,需要指定上限
    se = multiprocessing.Semaphore(3)
    for i in range(1, 10):
        p = multiprocessing.Process(target=run, args=('num'+str(i), se))
        p.start()   

进程池 简化进程的管理 统一管理 可以设置回调

import multiprocessing
import random
import time

# 进程任务结束的回调函数,参数时进程函数的返回值
def callback(num):
	print(num, '进程回调函数')

def task(num):
    print(num, '开始')
    t = random.random() * 3
    time.sleep(t)
    print(num, '进程执行了{}秒'.format(t))
    print(num, '结束')
    return num   

if __name__ == '__main__':  
    print('主进程开始')
    # 获取CPU核心数
    cpu_count = multiprocessing.cpu_count()
    # print(cpu_count)
    # 创建进程池:容量一般不超过CPU核心数
    pool = multiprocessing.Pool(cpu_count)
    # 循环创建进程,然后添加到进程池
    for i in range(1, 6):
        # 向进程池添加进程
        # func:进程任务,一个函数
        # args:以元组形式传递给进程函数的参数
        # kwargs:以字典形式传递给进程函数的参数
        pool.apply_async(func=task, args=(i,), callback=callback)
	# 关闭进程池,之后就不能再添加进程了
	pool.close()
	# 等待进程池结束
	pool.join()
	print('主进程结束')

数据共享

全局变量:无法在多个进程之间共享

import multiprocessing

# 多进程之间不能进行全局变量共享
num = 100

def run():
    global num
    print('子进程开始')
    num += 10
    # print('子进程:', num)
    print('子进程结束')
 
if __name__ == '__main__':
    print('主进程开始')
    p = multiprocessing.Process(target=run)
    p.start()
    p.join()
    print('主进程结束', num)   

管道

import multiprocessing

def run(p_a):
    # 子进程接收数据
    recv = p_a.recv()
    print('子进程接收到数据:', recv)
    # 子进程发送数据
    p_a.send('world')
    print('子进程结束') 
    
if __name__ == '__main__':
    # 创建管道
    # duplex:是否是全双工,默认为True
    # 半双工:p_a只能接收数据,p_b只能发送数据
    p_a, p_b = multiprocessing.Pipe()
    # 创建子进程
    p = multiprocessing.Process(target=run, args=(p_a,))
    p.start()
    # 主进程发送数据
    p_b.send('hello')
    p.join()
    # 主进程接收子进程发来的数据
    print('主进程结束', p_b.recv())

队列

import multiprocessing

if __name__ == '__main__':
    # 创建一个队列,指定容量
    q = multiprocessing.Queue(3)
    # 判断是否为空
    print(q.empty())

    # 向队列中添加数据
    q.put('how')
    q.put('are')
    q.put('you')

    # 判断是否已满
    print(q.full())
    # 若队列已满,再放数据则会阻塞
    # q.put('hello')
    # 若队列已满,则会崩溃
    # q.put_nowait('hello')

    # 获取数据
    print(q.get())
    # print(q.qsize())
    print(q.get())
    print(q.get())
    # 若队列已空,再获取数据会阻塞
    # print(q.get())
    # 若队列已空,再获取数据会崩溃
    # print(q.get_nowait())
    # 队列长度(队列中的数据数量)
    print(q.qsize())
    # 队列关闭
    q.close()

自定义进程类

说明:将进程处理封装成类,要求继承自multiprocessing.Process

示例:

from multiprocessing import Process
import time

class DownloadProcess(Process):
    def __init__(self, file):
        super().__init__()
        self.file = file

	# 在调用start方法后会自动调用
    # 改方法就是进程任务,无需单独指定
	def run(self):
		print('{}文件开始下载'.format(self.file))
        for i in range(1, 6):
            time.sleep(1)
            print('进度{}%'.format(i * 20))
		print('{}文件下载完成'.format(self.file))
        
if __name__ == '__main__':
    print('主进程开始')
    dp = DownloadProcess('meinv.jpg')
    dp.start()
    dp.join()
    print('主进程结束')
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值