multiprocessing模块介绍
【一】multiprocessing模块介绍
-
python中的多线程无法利用多核优势,如果想要充分地使用多核CPU的资源(os.cpu_count()查看),在python中大部分情况需要使用多进程。
-
- Python提供了multiprocessing。
- multiprocessing模块用来开启子进程,并在子进程中执行我们定制的任务(比如函数),该模块与多线程模块threading的编程接口类似。
-
multiprocessing模块的功能众多:
-
- 支持子进程、通信和共享数据、执行不同形式的同步
- 提供了Process、Queue、Pipe、Lock等组件。
-
需要再次强调的一点是:
-
- 与线程不同,进程没有任何共享状
- 进程修改的数据,改动仅限于该进程内。
【二】Process类介绍
p = multiprocessing.Process()
def __init__(self, group=None, target=None, name=None, args=(), kwargs={},
*, daemon=None):
# group : 参数表示一个组,但是我们不用
# target: 目标进程,表示调用的对象 要让子进程完成的任务
# name 当前子进程的名称
# args : 按照位置传参的参数(元组)
# kwargs :按照关键字传参的参数(字典)
# daemon: 守护进程
【三】Process类的对象的方法介绍
p = multiprocessing.Process()
# p 是实例后的对象
# 【1】p.start()
# 启动进程,并且会调用进程中 的 p.run()
# target:需要执行的子进程任务
self._target = target
def run(self):
'''
Method to be run in sub-process; can be overridden in sub-class
'''
if self._target:
self._target(*self._args, **self._kwargs)
# 【2】p.run()
# 启动自己的 run 方法,执行当前子进程函数
# 进程运行时的方法
# 真正的调用 自己传入的进程方法
-
p.terminate():
-
- 强制终止进程p,不会进行任何清理操作
- 如果p创建了子进程,该子进程就成了僵尸进程,使用该方法需要特别小心这种情况。
- 如果p还保存了一个锁那么也将不会被释放,进而导致死锁.
-
p.is_alive():
-
- 如果p仍然运行,返回True
-
p.join([timeout]):
-
- 主线程等待p终止(强调:是主线程处于等的状态,而p是处于运行的状态)。
- timeout是可选的超时时间
- 需要强调的是,p.join只能join住start开启的进程,而不能join住run开启的进程
【四】Process类的对象属性介绍
-
p.daemon:
-
- 默认值为False
- 如果设为True,代表p为后台运行的守护进程
- 当p的父进程终止时,p也随之终止
- 并且设定为True后,p不能创建自己的新进程,必须在p.start()之前设置
-
p.name:
- 获取当前子进程的名称
-
p.pid:
- 获取当前子进程的pid(进程号)
-
p.exitcode:
- 进程在运行时为None、如果为–N,表示被信号N结束(了解即可)
-
p.authkey:
- 进程的身份验证键,默认是由os.urandom()随机生成的32字符的字符串。
- 这个键的用途是为涉及网络连接的底层进程间通信提供安全性,这类连接只有在具有相同的身份验证键时才能成功(了解即可)
-
p.exitcode:
- 获取当前子进程的父进程的进程号
【1】Process 对象方法
import random
import multiprocessing
import os
import time
from multiprocessing import current_process
def work(name):
print(
f"{name} is starting ... pid is {current_process().pid}... os_pid is {os.getpid()}... os_ppid is {os.getppid()}")
sleep_time = random.randint(1, 6)
print(f"{name} is starting sleeping {sleep_time} seconds...")
time.sleep(sleep_time)
print(f"{name} is ending sleeping {sleep_time} seconds...")
print(
f"{name} is ending ... pid is {current_process().pid}... os_pid is {os.getpid()}... os_ppid is {os.getppid()}")
def main():
# 创建一个子进程
task_list = []
for i in range(0, 5):
task = multiprocessing.Process(target=work, # args = (f'task_{i}')
kwargs={'name': f'task_{i}'})
task.start()
print('terminate before ...', task.is_alive())
# 临时杀死
task.terminate()
task_list.append(task)
# 启动子线程
for task in task_list:
task.join()
print('terminate after ...', task.is_alive()) # 帮我们将当前子进程杀死
if __name__ == '__main__':
print(
f"main process is starting ... pid is {current_process().pid} ... os_pid is {os.getpid()} ... os_ppid is {os.getppid()}")
start_time = time.time()
main()
end_time = time.time()
print(
f"main process is ending ... pid is {current_process().pid} ... os_pid is {os.getpid()} ... os_ppid is {os.getppid()}")
# main process is starting ... pid is 7280 ... os_pid is 7280 ... os_ppid is 16464
# terminate before ... True
# terminate before ... True
# terminate before ... True
# terminate before ... True
# terminate before ... True
# terminate after ... False
# terminate after ... False
# terminate after ... False
# terminate after ... False
# terminate after ... False
# main process is ending ... pid is 7280 ... os_pid is 7280 ... os_ppid is 16464
# 【一】查看当前进程的进程ID
# 【1】进程ID : 指的是某个应用程序运行在系统之上的标志
# 【2】查看所有进程 win : cmd ---> tasklist / mac linux ---> 打开终端 ---> pas aux
# 【3】过滤端口 : win : cmd ---> tasklist|findstr PORT/PID / mac linux ---> 打开终端 ---> pas aux|grep PORT/PID
# 【4】在代码中查看进程ID
# (1)from multiprocessing import current_process
# (2)获取当前进程的PID
# current_process().pid == os.getpid()
# (3)查看当前进程的父ID
# os.getppid()
# 【二】杀死子线程
# task.terminate()
# 【三】查看当前线程或进程是够存活
# task.is_alive()