首先,先从多任务讲起:
现代操作系统(Windows、Mac OS X、Linux、UNIX等)都支持"多任务"
什么叫多任务???
操作系统同时可以运行多个任务
早期电脑都是单核cpu,他执行任务原理:
操作系统轮流让各个任务交替执行,QQ执行2Us,切换到微信,执行2Us,
再切换到陌陌,执行2Us,……。表面上看,每个任务反复执行下去,但是CPU调度
执行太快了,导致我们感觉就像所有任务都在同时执行一样。
现在是多核CPU实现多任务原理:
真正的并行执行多任务只能在多核CPU上实现,但是由于任务数量远远多于CPU核心数量
所以,操作系统也会自动把很多任务轮流调度到每个核心上的执行
并发:看上去一起执行,任务数多于核心数
并行:真正一起执行,任务数小于等于CPU核心数
实现多任务的方式:
1、多进程模式
2、多线程模式(常用)
3、协程模式(在开发中,很少用)
4、多进程+多线程 模式
接下来讲讲进程:
任务管理器:里面都是进程
对于操作系统而言,一个任务就是一个进程
进程是系统中程序执行和资源分配的基本单位,每个进程都有自己的数据段(存储数据),
代码段(存储代码)、和堆(存储一些对象的)栈(普通的变量就在栈上)段。
进程的目的:实现多任务,提高我们的执行效率
进程: 就是创建一个任务,让它去执行其他的功能
===============================================================================
from time import sleep
def run():
while True:
print("sunck is a nice man")
sleep(1.2)
if __name__ == '__main__':
while True:
print("sunck is a good man")
sleep(1)
# 不会执行 run 方法,只有上面的while循环结束才可以执行
# 要让这个两个任务同时执行,就是多任务
run()
运行结果:
sunck is a good man
sunck is a good man
sunck is a good man
sunck is a good man
sunck is a good man
sunck is a good man
===============================================================================
multiprocessing 库
multiple: adj.数量多的;多种多样的;
n.倍数;
processing: v.处理;加工;
n.过程;加工处理;处置;进行;
adj.经过特殊加工的;(用化学方法等)处理过的;
在linux下可以使用C语言的方法fork实现多进程,但是它不支持window,
但是这个三方库multiprocessing库是一个跨平台版本的多进程模块
提供了一个Process类来代表一个进程对象
所以我们要使用多进程就要引入multiprocessing库
import os
from multiprocessing import Process
from time import sleep
# 子进程需要执行的代码
def run(adj):
# os.getpid() 获取当前进程ID号
# os.getppid() 获取当前进程的父进程ID号
while True:
print("sunck is a %s man--%s--%s"%(adj, os.getpid(),os.getppid()))
sleep(1.2)
if __name__ == '__main__':
print("主(父)进程启动")
# os.getpid() 获取当前父进程ID号
print(os.getpid())
# 创建一个子进程(在父进程下创建一个进程,故称为该进程的子进程)
p = Process(target=run, args=("nice",))
# target:说明 该子进程要执行的任务、代码、函数
# args:可以给target的函数传参数,是一个元组类型,单个参数要加逗号,
# 启动进程
p.start()
while True:
print("sunck is a good man")
sleep(1)
运行结果:
主(父)进程启动
1975
sunck is a good man
sunck is a nice man--1976--1975
sunck is a good man
sunck is a nice man--1976--1975
===============================================================================
'''全局变量在多个进程中是不能共享的'''
from multiprocessing import Process
from time import sleep
NUM = 100
def run():
print("子进程开始")
global NUM
NUM += 1
print(NUM)
print("子进程结束")
if __name__ == '__main__':
print("父进程开始")
p = Process(target=run)
p.start()
p.join()
print(NUM)
# 在子进程中修改全局变量对父进程中的全局变量没有影响
# 为什么没影响呢?因为他在创建子进程时,对全局变量做了一个备份,父进程中的与子进程中的
# NUM是两个完全不同的变量
print("父进程结束--%d" % NUM)
运行结果:
父进程开始
子进程开始
101
子进程结束
100
父进程结束--100
# 父子进程的先后执行顺序
from multiprocessing import Process
from time import sleep
def run(args):
print("子进程启动")
sleep(3)
print("子进程结束")
if __name__ == '__main__':
print("主(父)进程启动")
p = Process(target=run, args=("nice",))
p.start()
# 父进程的结束不能影响子进程,让父进程等待子进程,再执行父进程
p.join()
print("父进程结束")
'''
进程池
'''
import os
import time
import random
# 为了对多个进程好管理,使用进程池
# from multiprocessing import Process
from multiprocessing import Pool
def run(name):
print('子进程%s启动--%s' % (name, os.getpid()))
strat = time.time()
time.sleep(random.choice([1, 2, 3]))
end = time.time()
print('子进程%s结束--%s--耗时%.2f' % (name, os.getpid(), end-strat))
if __name__ == '__main__':
print('父进程启动')
# 创建多个进程
# 进程池
# 4:表示可以同时执行的进程数量
# 参数可以写,pool默认大小是CPU核心数
pp = Pool(4)
# 创建进程,创建的进程数要大于CPU核心数,这样才能体验到多进程的效果
# 这里因为进程都是干一样的活,所以使用for循环创建进程
# 子进程的执行数据是没有顺序的。
for i in range(5):
# 创建进程,放进进程池,统一管理
pp.apply_async(run, args=(i,))
'''
如果每个进程干的活不一样,那就单独创建每一个进程,不要写for循环。
例:
pp.apply_async(func1, agrs=())
pp.apply_async(func2, agrs=())
pp.apply_async(func3, agrs=())
pp.apply_async(func4, agrs=())
pp.apply_async(func5, agrs=())
'''
# 在调用join之前,必须先调用close,并且在调用close之后,就不能再继续添加新的进程了
pp.close()
# 进程池对象调用的join,会等待进程池中的所有的子进程结束完毕,再去执行父进程。
pp.join()
print("父进程结束")
'''
运行结果: 这里进程看似0,1,2,3启动的,实际上,进程启动是没有顺序的。
父进程启动
子进程0启动--5251
子进程1启动--5252
子进程2启动--5253
子进程3启动--5254
子进程2结束--5253--耗时1.00
子进程0结束--5251--耗时1.00
子进程4启动--5253
子进程3结束--5254--耗时1.00
子进程1结束--5252--耗时2.00
子进程4结束--5253--耗时3.00
父进程结束
'''
#!/usr/bin/env python
# -*- coding:utf-8 -*-
# 多进程实现文件拷贝
import os
import time
from multiprocessing import Pool
# 实现文件的拷贝
def copy_file(read_file_path, write_file_path):
read_file = open(read_file_path, 'rb')
write_file = open(write_file_path, 'wb')
context = read_file.read()
write_file.write(context)
read_file.close()
write_file.close()
path = r''
to_path = r''
if __name__ == '__main__':
# 读取path下的所有文件
file_list = os.listdir(path)
start = time.time()
pp = Pool(2)
for file_name in file_list:
pp.apply_async(copy_file,
args=(os.path.join(path, file_name),
os.path.join(to_path, file_name)
)
)
pp.close()
pp.join()
end = time.time()
run_time = end - start
print('总耗时---%d' % run_time)
#二次封装的文件名,一般是:自己的名字+第三方库的名称
import os
import time
from multiprocessing import Process
class SunckProcess(Process):
def __init__(self, name):
super().__init__()
self.name = name
def run(self):
super().run()
print('子进程(%s-%s)启动' % (self.name, os.getpid()))
# 子进程的功能
time.sleep(3)
print('子进程(%s-%s)结束' % (self.name, os.getpid()))
==================================================================
from sunckProcess import SunckProcess
if __name__ == '__main__':
print('父进程启动')
# 创建子进程
p = SunckProcess('test')
# 在这里不要调用进程里面的run方法,调用它的start就会自动调用进程对象的run方法
p.start()
p.join()
print("父进程结束")