多进程操作
multiprocessing
模块是 Python 标准库中用于支持多进程编程的模块。它提供了在多核和多处理器系统上创建和管理进程的工具,使得开发者能够更方便地进行并行和并发编程。
Process类的介绍
(1)创建进程的类
| Process([group [, target [, name [, args [, kwargs]]]]]) |
- 由该类实例化得到的对象,表示一个子进程中的任务(尚未启动)
强调:
- 需要使用关键字的方式来指定参数
- args指定的为传给target函数的位置参数,是一个元组形式,必须有逗号
(2)参数介绍
- group参数未使用,值始终为None
- target表示调用对象,即子进程要执行的任务
- args表示调用对象的位置参数元组,args=(1,2,'ly',)
- kwargs表示调用对象的字典,kwargs=
- name为子进程的名称
(3)方法介绍
p.start()
:
p.run()
:
- 进程启动时运行的方法,正是它去调用target指定的函数,我们自定义类的类中一定要实现该方法
p.terminate()
:
- 强制终止进程p,不会进行任何清理操作
- 如果p创建了子进程,该子进程就成了僵尸进程,使用该方法需要特别小心这种情况
- 如果p还保存了一个锁那么也将不会被释放,进而导致死锁
p.is_alive()
:
p.join([timeout])
:
- 主线程等待p终止(强调:是主线程处于等的状态,而p是处于运行的状态)。
- timeout是可选的超时时间
- 需要强调的是,p.join只能join住start开启的进程,而不能join住run开启的进程
(4)属性介绍
p.daemon
:
- 默认值为False
- 如果设为True,代表p为后台运行的守护进程
- 当p的父进程终止时,p也随之终止
- 并且设定为True后,p不能创建自己的新进程,必须在p.start()之前设置
p.name
:
p.pid
:
p.exitcode
:
- 进程在运行时为None、如果为–N,表示被信号N结束(了解即可)
p.authkey
:
- 进程的身份验证键,默认是由os.urandom()随机生成的32字符的字符串。
- 这个键的用途是为涉及网络连接的底层进程间通信提供安全性,这类连接只有在具有相同的身份验证键时才能成功(了解即可)
Process类的使用
(1)多进程的创建方式
在windows中Process()必须放到 if __name == 'main__':
下
(1)直接使用Process方法
| import multiprocessing |
| |
| |
| def run_task(i): |
| print(f'当前的进程为:>>>{i}') |
| |
| |
| def main_task(): |
| for i in range(1, 10): |
| |
| task = multiprocessing.Process(target=run_task, args=(i,)) |
| |
| task.start() |
| |
| |
| if __name__ == '__main__': |
| main_task() |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
(2)继承Process类
| import multiprocessing |
| |
| |
| def run_task(i): |
| print(f'当前的进程为:>>>{i}') |
| |
| |
| def main_task(): |
| for i in range(1, 10): |
| |
| task = multiprocessing.Process(target=run_task, args=(i,)) |
| |
| task.start() |
| |
| |
| class MyProcess(multiprocessing.Process): |
| def __init__(self,i): |
| super().__init__() |
| self.i = i |
| def run(self): |
| print(f'当前是:>>>{self} | 参数为:>>>{self.i}') |
| |
| def main_two(): |
| for i in range(1,10): |
| task = MyProcess(i=i) |
| task.start() |
| |
| |
| if __name__ == '__main__': |
| main_two() |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
(2)进程之间的内存空间是隔离的
- 每一个子进程之间的数据是相互隔离的
- 在执行子进程代码时,只修改自己子进程内的数据,不会影响到其他的子进程
| import multiprocessing |
| |
| number = 99 |
| |
| |
| def run_task(i): |
| global number |
| number += 1 |
| print(f'这是子进程{i}:>>>{number}') |
| |
| |
| def main_one(): |
| for i in range(1, 5): |
| task = multiprocessing.Process(target=run_task, args=(i,)) |
| task.start() |
| |
| |
| if __name__ == '__main__': |
| main_one() |
| |
| |
| |
| |
(3)socket通信变成并发的形式
(1)服务端
| from socket import * |
| from multiprocessing import Process |
| |
| server=socket(AF_INET,SOCK_STREAM) |
| server.setsockopt(SOL_SOCKET,SO_REUSEADDR,1) |
| server.bind(('127.0.0.1',8080)) |
| server.listen(5) |
| |
| def talk(conn,client_addr): |
| while True: |
| try: |
| msg=conn.recv(1024) |
| if not msg:break |
| conn.send(msg.upper()) |
| except Exception: |
| break |
| |
| if __name__ == '__main__': |
| while True: |
| conn,client_addr=server.accept() |
| p=Process(target=talk,args=(conn,client_addr)) |
| p.start() |
(2)客户端
| from socket import * |
| |
| client=socket(AF_INET,SOCK_STREAM) |
| client.connect(('127.0.0.1',8080)) |
| |
| |
| while True: |
| msg=input('>>: ').strip() |
| if not msg:continue |
| |
| client.send(msg.encode('utf-8')) |
| msg=client.recv(1024) |
| print(msg.decode('utf-8')) |
Process对象的join方法
(1)非join方法 并行
| from multiprocessing import Process |
| import time |
| |
| |
| |
| def task(task_name, task_time): |
| print(f'这是进程:>>>>{task_name} 需要运行:>>>>{task_time}s') |
| |
| |
| time.sleep(task_time) |
| |
| print(f'这是进程:>>>>{task_name} 执行完毕') |
| |
| |
| if __name__ == '__main__': |
| |
| p_list = [] |
| |
| |
| |
| |
| for i in range(1, 4): |
| p = Process(target=task, args=(i, i,)) |
| p_list.append(p) |
| |
| start_time = time.time() |
| |
| |
| |
| for p in p_list: |
| p.start() |
| |
| |
| |
| print(f'这是进程的主程序') |
| |
| |
| print(f'这是主程序运行的总耗时:{time.time() - start_time}') |
| |
| |
| |
| |
| |
| |
| |
| |
| |
(2)join方法 串行
- 在启动每个子进程后立即调用了
p.join()
,这样的话主程序会在每个子进程启动后立即等待该子进程执行完毕,然后再启动下一个子进程。这导致了串行执行的效果,而不是并行。
| from multiprocessing import Process |
| import time |
| |
| |
| def task(task_name, task_time): |
| print(f'这是进程:>>>>{task_name} 需要运行:>>>>{task_time}s') |
| time.sleep(task_time) |
| print(f'这是进程:>>>>{task_name} 执行完毕') |
| |
| |
| if __name__ == '__main__': |
| |
| p_list = [] |
| |
| |
| |
| |
| for i in range(1, 4): |
| p = Process(target=task, args=(i, i,)) |
| p_list.append(p) |
| |
| start_time = time.time() |
| |
| |
| |
| for p in p_list: |
| p.start() |
| p.join() |
| print(f'这是进程的主程序') |
| print(f'这是程序运行的总耗时:{time.time() - start_time}') |
| |
| |
| |
| |
| |
| |
| |
| |
| |
(3)join方法 并行
| from multiprocessing import Process |
| import time |
| |
| |
| |
| def task(task_name, task_time): |
| print(f'这是进程:>>>>{task_name} 需要运行:>>>>{task_time}s') |
| |
| |
| time.sleep(task_time) |
| |
| print(f'这是进程:>>>>{task_name} 执行完毕') |
| |
| |
| if __name__ == '__main__': |
| |
| p_list = [] |
| |
| |
| |
| |
| for i in range(1, 4): |
| p = Process(target=task, args=(i, i,)) |
| p_list.append(p) |
| |
| |
| start_time = time.time() |
| |
| |
| task_list = [] |
| |
| |
| |
| for p in p_list: |
| p.start() |
| task_list.append(p) |
| |
| |
| for task in task_list: |
| task.join() |
| |
| |
| print(f'这是进程的主程序') |
| |
| |
| print(f'这是程序运行的总耗时:{time.time() - start_time}') |
| |
| |
| |
| |
| |
| |
| |
| |
| |
Process对象的其他方法或属性
(1)什么是进程号
- 一台计算机上面运行着很多进程,那么计算机是如何区分并管理这些进程服务端呢?
(2)如何查看进程号
(3)如何根据指定进程号查看进程
- Windows系统
- CMD 命令行
tasklist |findstr PID
即可查看
(4)查看当前进程的进程号current_process().pid
方法
| from multiprocessing import Process, current_process |
| import time |
| |
| |
| def task(): |
| |
| print(f'当前程序:>>>>{current_process().pid} 正在运行') |
| time.sleep(2) |
| |
| |
| if __name__ == '__main__': |
| p = Process(target=task) |
| p.start() |
| |
| print(f'这是主程序:>>>{current_process().pid}') |
| |
| |
(5)查看当前进程的进程号os.getpid()
方法
| from multiprocessing import Process |
| import os |
| import time |
| |
| |
| def task(): |
| |
| print(f'当前程序:>>>>{os.getpid()} 正在运行') |
| time.sleep(2) |
| |
| |
| if __name__ == '__main__': |
| p = Process(target=task) |
| p.start() |
| |
| print(f'这是主程序:>>>{os.getpid()}') |
| |
| |
| |
(6)查看当前进程的父进程的进程号os.getppid()
方法
| from multiprocessing import Process |
| import os |
| import time |
| |
| |
| def task(): |
| |
| print(f'当前程序:>>>>{os.getpid()} 正在运行') |
| |
| print(f'当前程序的父进程:>>>>{os.getppid()} 正在运行') |
| time.sleep(2) |
| |
| |
| if __name__ == '__main__': |
| p = Process(target=task) |
| p.start() |
| |
| print(f'这是主程序:>>>{os.getpid()}') |
| print(f'这是主程序的父进程:>>>{os.getppid()}') |
| |
| |
| |
| |
| |
(7)杀死当前进程p.terminate()
| from multiprocessing import Process |
| import time |
| |
| |
| def task(): |
| print("子进程开始执行") |
| time.sleep(5) |
| print("子进程执行完毕") |
| |
| |
| if __name__ == '__main__': |
| |
| p = Process(target=task) |
| |
| |
| p.start() |
| |
| |
| time.sleep(2) |
| |
| |
| p.terminate() |
| |
| print("主程序执行完毕") |
| |
| |
| |
(8)判断当前进程是否存活p.is_alive()
| from multiprocessing import Process |
| import time |
| |
| |
| def task(): |
| print("子进程开始执行") |
| time.sleep(5) |
| print("子进程执行完毕") |
| |
| |
| if __name__ == '__main__': |
| |
| p = Process(target=task) |
| |
| |
| p.start() |
| |
| |
| while p.is_alive(): |
| print("主程序:子进程还在执行...") |
| time.sleep(1) |
| |
| print("主程序:子进程已经结束") |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通