文章目录
- Python 进阶篇-系列文章全篇
- 一、进程以及状态
- 二、[重点]进程-基本使用
- 三、[重点]进程-名称、PID
- 四、[重点]进程-参数传递、全局变量问题
- 五、[重点]进程-守护主进程
- 六、进程、线程对比
- 七、[重点]消息队列-基本操作
- 八、消息队列-常见判断
- 九、[重点]Queue实现进程间通信
- 十、[重点]进程池Pool
- 十一、进程池中的Queue
- 十二、案例:文件夹copy器(多进程版)
- 十三、[重点]可迭代对象及检测方法
- 十四、[重、难点]迭代器及其使用方法
一、进程以及状态
- 进程:资源分配的基本单位,也是线程的容器
- 进程的状态:
* 新建
* 就绪
* 运行
* 等待
* 死亡
二、[重点]进程-基本使用
- 进程使用的步骤:
- 导入模块
import multiprocessing
- 创建子进程对象
process_obj = multiprocessing.Process(target=work1)
- 启动子进程
process_obj.start()
三、[重点]进程-名称、PID
- 获取进程的名称
multiprocessing.current_process()
设置名称:
multiprocessing.Process(target=xxxx, name=“进程名称”)
- 获取进程的编号
- multiprocessing.current_process().pid
- os.getpid()
- 获取进程的父id
os.getppid()
- 结束进程
Kill -9 进程的编号
四、[重点]进程-参数传递、全局变量问题
- 进程的参数传递
- args 元组
- kwargs 字典
- 混合args 和 kwargs
# 1)使用 args 传递元组 # 2)使用 kwargs 传递字典 # 3)混合使用 args 和 kwargs # process_obj = multiprocessing.Process(target=work1, args=(10, 100,1000)) # process_obj = multiprocessing.Process(target=work1, kwargs={"c": 1000, "a": 10, "b": 100}) process_obj = multiprocessing.Process(target=work1, args=(10, ), kwargs={"c": 1000, "b": 100})
- 进程间共享全局变量的问题
进程间是不能够共享全局变量
底层原理:子进程会复制主进程的资源到内部运行
五、[重点]进程-守护主进程
- 进程守护: 子进程和主进程的一种约定,当主进程结束的时候,子进程也随之结束
process_obj.daemon = True
- 结束子进程
# terminate() 终止子进程的执行 process_obj.terminate()
六、进程、线程对比
- 进程和线程的对比
- 进程是资源分配的基本单位,线程是CPU调度的基本单位
- 进程运行需要独立的内存资源, 线程需要到的是必不可少的一点资源
- 进程切换慢,线程切换更快
- 线程不能独立运行,必须运行在进程中(进程能提供资源)
- CPU密集型 进程优先, I/O 密集型使用线程
- 程序更稳定进程,线程相比较不够稳定
- 不是非此即彼,而是组合使用
七、[重点]消息队列-基本操作
- 消息队列的学习的目的:为了实现进程间的通信
- 队列的创建:
- 导入模块 multiprocessing
- multiprocessing.Queue(5) # 队列长度为5
- 队列的操作:
- 放入值 queue.put(值) —>从队列尾部放入值
- 取值: queue.get() --> 从队列头部取值
- xxxx_nowait() 方式
- 放入值 put_nowait() 特点:队列未满,同put() 但是队列已满,会报错,不等待
- 取值 get_nowait() 特点:队列未空,同get() 但是队列已空,会报错,不等待
八、消息队列-常见判断
- 常见的判断
- full() 判断是否已满
- empty() 判断是否为空
- 取出队列中消息的数量
- qsize()
九、[重点]Queue实现进程间通信
- 思路:利用队列在两个进程间进行传递,进而实现数据共享
- write_queue(queue)
- read_queue(queue)
- 创建一个空队列
- 把空队列作为参数,先把队列传递给写进程,然后把队列再传递给读进程
- join() 优先让一个进程先执行完成,另外一个进程才能启动
十、[重点]进程池Pool
- 进程池:是一个进程的容器,可以自动帮我们创建指定数量的进程,并且管理进程及工作
- 创建方法:
- 导入模块
- 创建进程池
pool = multiprocessing.Pool(3)
- 工作方式:
- 同步方式:
pool.apply(函数名,(参数1,参数2,…))
进程池中的进程,一个执行完毕后另外一个才能执行,多个进程执行有先后顺序 - 异步方式:
pool.apply_async(函数名,(参数1,参数2,…))
进程池中的进程,多个进程同时执行,没有先后顺序
1) 进程池要 close() 表示不再接受新的任务
pool.close()
- 2)还要join() 表示让主进程等待进程池执行结束后再退出
pool.join()
十一、进程池中的Queue
- 获取方法:
# 1、创建进程池 pool = multiprocessing.Pool(2) # 2、创建进程池中的队列 queue = multiprocessing.Manager().Queue(5)
# apply_async() 返回值 ApplyResult对象,该对象由一个 wait() 的方法 # wait() 方法类似join() 表示先让当前进程执行完毕,后续进程才能启动 result = pool.apply_async(write_queue, (queue, )) result.wait() pool.apply_async(read_queue, (queue, )) # close()表示不再接收新的任务 pool.close() # 主进程会等待进程池执行结束后再退出 pool.join()
十二、案例:文件夹copy器(多进程版)
- 思路:
./test/ ---------> /home/demo/Desktop/test/
思路:
1、定义变量,保存源文件夹、目标文件夹所在的路径
2、在目标路径创建新的文件夹
3、获取源文件夹中的所有的文件(列表)
4、遍历列表,得到所有的文件名
5、定义函数,进行文件拷贝文件拷贝函数:
参数: 源文件夹路径 目标文件夹路径 文件名
1、拼接源文件和目标文件的具体路径
2、打开源文件,创建目标文件
3、读取源文件的内容,写入到目标文件中 (while)
- 进程池拷贝文件
# 创建进程池 pool = multiprocessing.Pool(3) # 4、遍历列表,得到所有的文件名 for file_name in file_list: # print(file_name) # 5、定义函数,进行文件拷贝 # copy_work(source_dir, dest_dir, file_name) pool.apply_async(copy_work, (source_dir, dest_dir, file_name)) # close() 不再接收新的任务 pool.close() # 让主进程等待进程池结束后在退出 pool.join()
- 创建文件夹
os.mkdir(路径)
- 获取文件夹中的内容
os.listdir(路径)
十三、[重点]可迭代对象及检测方法
- 可迭代对象
# 1、可遍历对象就是可迭代对象 # 2、列表、元组、字典、字符串都是可迭代对象 # 3、100 和 自定义myclass 默认都是不可以迭代的 # 4、myclass 对象所属的类 MyClass 如果包含了 __iter__() 方法,此时 # myclass就是一个可迭代对象 # 5、可迭代对象的本质:对象所属的类中包含了 __iter__() 方法
- 可迭代对象的检测:
# 6、检测一个对象是否可以迭代,用 isinstance() 函数检测
十四、[重、难点]迭代器及其使用方法
- 迭代器的作用:
1) 记录当前迭代的位置 2)配合next() 获取可迭代对象的下一个元素值
- 获取迭代器
iter(可迭代对象)
- 获取可迭代对象的值
next(迭代器)
- for循环的本质:
1)通过 iter(要遍历的对象) 获取要遍历的对象的迭代器
2)next(迭代器)获取下一个元素
3)帮我们捕获了 StopIteration 异常
- 自定义迭代器类
# 自定义迭代器类,满足2点 # 1)必须含有 __iter__() # 2) 必须含有 __next__()class MyIterator(object): def __iter__(self): pass # 当 next(迭代器) 的时候,会自动调用该方法 def __next__(self): pass