赞
踩
多任务是指在同一时间执行多个任务,多任务的两种表现形式:
1.并行
:在同一时间内交替交替
多个任务
2.并发
:在同一时间内同时
去执行多个任务
实现多任务通常有多进程、多线程以及协程
进程是资源分配的最小单位,是操作系统进行资源分配的调度运行的基本单位(通俗理解:一个运行中的程序就是一个进程,例如:qq、微信等)
1.导入进程包
import mutiprocessing
2.创建进程对象
进程对象 = mutiprocessing.Process(args)
args:有三个常用参数,详情如下
参数 | 解释 |
---|---|
target | 执行的目标任务名,这里指的是函数(方法)名 |
name | 进程名字,一般不设置 |
group | 进程组,目前只能使用None |
3.启动进程执行任务
进程对象.start()
import time def sing(): for i in range(3): print(f'sing{i}') time.sleep(0.5) def dance(): for i in range(3): print(f'dance{i}') time.sleep(0.5) if __name__ == '__main__': t1 = time.time() sing() dance() print(time.time() - t1)
执行结果:
sing0 sing1 sing2 dance0 dance1 dance2 3.0040132999420166
import time, multiprocessing def sing(): for i in range(3): print(f'sing{i}') time.sleep(0.5) def dance(): for i in range(3): print(f'dance{i}') time.sleep(0.5) if __name__ == '__main__': t1 = time.time() sing_processing = multiprocessing.Process(target=sing) dance_processing = multiprocessing.Process(target=dance) sing_processing.start() dance_processing.start() sing_processing.join() #等待子进程结束后再往下执行 dance_processing.join() print(time.time() - t1)
执行结果:
sing0 dance0 sing1 dance1 sing2 dance2 1.7761003971099854
参数名 | 解释 |
---|---|
args | 以元组的形式给任务传参 |
kwargs | 以字典的形式给任务传参 |
注意
:
1:元组传参一定和参数顺序一致
2:字典传参时字典的key要和参数名一致
import time, multiprocessing def sing(name, num): for i in range(num): print(f'{name}在唱歌...') time.sleep(0.5) def dance(name, num): for i in range(num): print(f'{name}在跳舞...') time.sleep(0.5) if __name__ == '__main__': t1 = time.time() sing_processing = multiprocessing.Process(target=sing, args=('小明', 3)) dance_processing = multiprocessing.Process(target=dance, kwargs={'name': '蔡徐坤', 'num': 3}) sing_processing.start() dance_processing.start() sing_processing.join() #等待子进程结束后再往下执行 dance_processing.join() print(time.time() - t1)
执行结果:
蔡徐坤在跳舞... 小明在唱歌... 蔡徐坤在跳舞... 小明在唱歌... 蔡徐坤在跳舞... 小明在唱歌... 1.668849229812622
当程序中进程的数量越来越多时,如果没有办法区分主进程和子进程还有不同的子进程,那么就无法进行有效的进程管理,为了方便管理实际上每个进程都是有自己的编号的。
1.获取当前进程编号:
os.getpid()
2.获取当前父进程编号:
os.getppid()
import time, multiprocessing, os def sing(name, num): print(f'唱歌进程编号:{os.getpid()}') print(f'唱歌父进程编号:{os.getppid()}') for i in range(num): print(f'{name}在唱歌...') time.sleep(0.5) def dance(name, num): print(f'跳舞进程编号:{os.getpid()}') print(f'跳舞父进程编号:{os.getppid()}') for i in range(num): print(f'{name}在跳舞...') time.sleep(0.5) if __name__ == '__main__': t1 = time.time() sing_processing = multiprocessing.Process(target=sing, args=('小明', 3)) dance_processing = multiprocessing.Process(target=dance, kwargs={'name': '蔡徐坤', 'num': 3}) sing_processing.start() dance_processing.start() sing_processing.join() #等待子进程结束后再往下执行 dance_processing.join() print(time.time() - t1)
执行结果:
唱歌进程编号:14388
跳舞进程编号:2460
唱歌父进程编号:3472
小明在唱歌...
跳舞父进程编号:3472
蔡徐坤在跳舞...
小明在唱歌...
蔡徐坤在跳舞...
小明在唱歌...
蔡徐坤在跳舞...
1.6702723503112793
主进程会等待
所有子进程执行结束再结束
,设置守护主进程就是在主进程结束后不再执行子进程剩余的工作
import time, multiprocessing
def work():
for i in range(10):
print('子进程执行中...')
time.sleep(0.2)
if __name__ == '__main__':
# 方法1:multiprocessing.Process(target=work, daemon=True)
# 方式2:子进程对象.daemon=True
work_processing = multiprocessing.Process(target=work, daemon=True)
work_processing.start()
time.sleep(0.8)
print('主进程执行结束...')
执行结果:
子进程执行中...
子进程执行中...
子进程执行中...
子进程执行中...
主进程执行结束...
子进程10次还没执行完毕,主进程结束,子进程也会结束
import os import multiprocessing def copy_file(source_dir, dest_dir, filename): with open(source_dir+ '/' + filename, 'rb') as source_file: with open(dest_dir+ '/' +filename, 'wb') as dest_file: while True: data = source_file.read(1024) if data: dest_file.write(data) else: break if __name__ == '__main__': #1.判断目标文件夹是否存在 if not os.path.exists('copy_file'): os.mkdir('copy_file') #2.遍历目标文件夹中的文件,获取文件名列表 dirlist = os.listdir('vidio') #3.利用多进程创建多个任务 for path in dirlist: copy_file_processing = multiprocessing.Process(target=copy_file, args=('vidio', 'copy_file', path)) copy_file_processing.start() print('dump!!!')
线程是程序执行的最小单位,同属一个进程的多个线程共享进程的全部资源,一个进程至少拥有一个线程。
1.导入线程包
import threading
2.通过线程类创建线程对象
线程对象 = threading.Thread(args)
args:有三个常用参数,详情如下
参数 | 解释 |
---|---|
target | 执行的目标任务名,这里指的是函数(方法)名 |
name | 线程名字,一般不设置 |
group | 线程组,目前只能使用None |
3.启动线程执行任务
线程对象.start()
threading.currentThread().getName
threading.currentThread().ident
线程的用法与进程相同,包括执行带参数的任务、守护主线程,只不过是将进程对象改为线程对象
import os import threading def copy_file(source_dir, dest_dir, filename): with open(source_dir+ '/' + filename, 'rb') as source_file: with open(dest_dir+ '/' +filename, 'wb') as dest_file: while True: data = source_file.read(1024) if data: dest_file.write(data) else: break if __name__ == '__main__': #1.判断目标文件夹是否存在 if not os.path.exists('copy_file'): os.mkdir('copy_file') #2.遍历目标文件夹中的文件,获取文件名列表 dirlist = os.listdir('vidio') #3.利用多进程创建多个任务 for path in dirlist: copy_file_threading = threading.Thread(target=copy_file, args=('vidio', 'copy_file', path)) copy_file_threading.start() print('dump!!!')
1.线程是依附在进程里面的,没有进程就没有线程
2.一个进程可以有多个线程,一个进程默认提供一个进程
1.创建进程的资源开销要比创建线程开销大
2.进程是操作系统分配资源的基本单位,而线程是CPU调度的基本单位
3.线程不能独立执行,必须依附在进程中
1.进程
2.线程
存放固定数量的进程/线程,然后把要执行的任务都放置在进程/线程池中,由进程/线程池去决定分配给哪个进程/线程完成任务,可重复使用进程/线程池
1.导入ProcessPoolExecutor包
from concurrent.futures import ProcessPoolExecutor
2.定义进程池目标函数
def fn(arg1, arg2...)
3.利用进程池执行任务
with ProcessPoolExecutor(num) as t: t.submit(fn, arg1, arg2...)
import os from concurrent.futures import ProcessPoolExecutor def copy_file(source_dir, dest_dir, filename): with open(source_dir+ '/' + filename, 'rb') as source_file: with open(dest_dir+ '/' +filename, 'wb') as dest_file: while True: data = source_file.read(1024) if data: dest_file.write(data) else: break if __name__ == '__main__': #1.判断目标文件夹是否存在 if not os.path.exists('copy_file'): os.mkdir('copy_file') #2.遍历目标文件夹中的文件,获取文件名列表 dirlist = os.listdir('vidio') #3.开辟50个进程执行任务 with ProcessPoolExecutor(50) as t: for path in dirlist: t.submit(copy_file, 'vidio', 'copy_file', path) print('dump!!!')
PS:线程池和进程池几乎一样,就把ProcessPoolExecutor更换为ThreadPoolExecutor
协程又称为微线程,是多任务的异步操作,协程的作用是在执行函数A的时候,可以中断A函数执行B函数,然后中断B函数继续执行A函数。协程的任务是主动切换的,
切换条件是IO
,遇到阻塞操作时自动切换,在微观上协程是一个一个任务的切换,在宏观上,我们看到的就是多个任务在执行。
注意:协程所做的一切都是单线程条件下
python对于协程的支持是通过生成器实现的,协程是遵循某些规则的生成器
__next__()
启动或者恢复generator的执行,相当于send(None)
send()
用于发送值给yield
def test(): print('start') n = 1 while True: r = yield n print('ok', r) n += 1 if __name__ == '__main__': # 创建生成器 gen = test() #启动生成器 res = gen.__next__() #相当于gen.send(None)操作 print(res) #1 res = gen.__next__() print(res) #2 res = gen.__next__() print(res) #3 #执行结果: ''' start 1 ok None 2 ok None 3 ''' res = gen.send(100) print(res) # 执行结果 ''' ok 100 4 ''' '''
代码解释:
当执行__next__操作的时候,进入内部函数开始执行,当第一次遇到yield(可以理解为return)的时候,在赋值给res之前直接返回,并且立即停止操作,下次__next__的时候再在上次断点的地方进行操作。
1.导入asyncio包
import asyncio
2.定义异步函数
async def fn(): pass
3.定义多个任务
async def func1(): print("你好啊,我是啊一") await asyncio.sleep(2) print("你好啊,我是啊一") async def func2(): print("你好啊,我是啊二") await asyncio.sleep(2) print("你好啊,我是啊二") async def func3(): print("你好啊,我是啊三") await asyncio.sleep(2) print("你好啊,我是啊三")
4.创建任务列表
asyncio.create_task(函数)
asyncio.wait(tasks)
import asyncio # 1.async 声明是个异步函数 async def func1(): print("你好啊,我是啊一") #await:挂起任务,执行下一个任务 await asyncio.sleep(2) #3.在异步函数中不能出现同步操作,否则异步中断 print("你好啊,我是啊一") async def func2(): print("你好啊,我是啊二") await asyncio.sleep(2) print("你好啊,我是啊二") async def func3(): print("你好啊,我是啊三") await asyncio.sleep(2) print("你好啊,我是啊三") async def main(): tasks = [ asyncio.create_task(func1()), #4.asyncio.create_task()创建任务 py3.8以后加上asyncio.create_task() asyncio.create_task(func2()), asyncio.create_task(func3()) ] await asyncio.wait(tasks) #5.任务列表 if __name__ == '__main__': loop = asyncio.get_event_loop() #6.定义异步对象 loop.run_until_complete(main()) #7.执行异步函数 loop.close()
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。