Process类参数介绍
group -------- 参数未使用, 值始终为None
target -------- 表示调用对象, 即子进程要执行的任务
args ---------- 表示调用对象的位置参数元组, args=(1,2,'hades',) 是一个元组形式,必须有逗号
kwargs ------- 表示调用对象的字典, kwargs={'name':'hades','age':18}
name --------- 为子进程的名称
Process类方法介绍
p.start() ----------------- 启动进程, 并调用该子进程中的p.run()
p.run() ------------------- 进程启动时运行的方法, 正是它去调用target指定的函数, 自定义类的类中一定要实现该方法
p.terminate() ----------- 强制终止进程p, 不会进行任何清理操作, 如果p创建了子进程, 该子进程就成了僵尸进程, 使用该方法需要特别小心这种情况.
如果p还保存了一个锁那么也将不会被释放, 进而导致死锁
p.is_alive() -------------- 判断进程是否存活, 如果p仍然运行, 返回True
p.join() ------------------- 主进程等待p子进程终止(是主进程处于等的状态,而p子进程处于运行的状态), 只能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字符的字符串.
这个键的用途是为涉及网络连接的底层进程间通信提供安全性,这类连接只有在具有相同的身份验证键时才能成功(了解知识点)
什么是进程
使用进程是要实现并发效果
进程就是一个正在进行/运行的程序, 换言之, 进程指的是一个程序的运行过程
程序vs进程:
程序: 只是一堆代码文件
进程: 程序运行的过程才是进程
串行: 一个任务完完整整地运行完毕, 再执行下一个任务, 按次序依次进行
判断串行的概念:
串行看起来就是一个一个运行的: 对
一个一个的运行就是串行: 错误
并发(切换+保存状态): 多个任务看起来是同时运行, 单核就可以实行并发
并行: 多个任务是真正意义上的同时运行, 只有多核才能实现并行
多道技术的产生背景: 就是想要在单核下实现并发
如何实现:
1. 空间上的复用: 将内存分为几部分, 每个部分放入一个程序的数据, 这样同一时间内存中就有了多道程序的数据, 为CPU在多个任务间切换做准备
2. 时间上的复用: 多个进程共享CPU的时间
关键点就是CPU在多个任务之间进行切换
有两种情况下会发生切换:
1. 一个任务占用CPU时间过长(没有遇到IO操作): 会降低效率
2. 一个任务在运行的过程中遇到IO操作: 可以提升效率
开启子进程的方式1
1 from multiprocessing import Process 2 import time 3 4 5 def task(name): 6 print('%s is running' % name) 7 time.sleep(3) 8 print('%s is done' % name) 9 10 11 # 在windows系统上开启子进程的操作必须放到该行代码下 12 if __name__ == '__main__': 13 p = Process(target=task, args=('子进程',)) # Process(target=task,kwargs={'name':'子进程'}) # 14 p.start() # 仅仅只是向操作系统发送一个创造子进程的信号 15 print('主')
终端打印:
开启子进程的方式2
1 from multiprocessing import Process 2 import time 3 4 5 class Myprocess(Process): 6 def __init__(self, name): 7 super().__init__() 8 self.name = name 9 10 def run(self): 11 print('%s is running' % self.name) 12 time.sleep(3) 13 print('%s is done' % self.name) 14 15 16 # 在windows系统上开启子进程的操作必须放到该行代码下 17 if __name__ == '__main__': 18 p = Myprocess('子进程') 19 p.start() # 仅仅只是向操作系统发送一个创造子进程的信号 20 p.join() 21 print('主')
终端打印:
join方法
1 from multiprocessing import Process 2 import time 3 4 5 def task(name, n): 6 print('%s is running' % name) 7 time.sleep(n) 8 print('%s is done' % name) 9 10 11 if __name__ == '__main__': 12 start = time.time() 13 p_l = [] 14 for i in range(1, 4): 15 p = Process(target=task, args=('子进程%s' % i, i)) 16 p_l.append(p) 17 p.start() 18 19 for p in p_l: 20 p.join() 21 stop = time.time() 22 print('主', (stop - start))
终端打印:
进程之间内存隔离
1 from multiprocessing import Process 2 3 n = 100 4 5 6 def task(): 7 global n 8 n = 0 9 10 11 if __name__ == '__main__': 12 p = Process(target=task, ) 13 p.start() 14 p.join() 15 print('主', n)
终端打印:
进程的PID
1 from multiprocessing import Process, current_process 2 import time, os 3 4 5 def task(): 6 print('子进程[%s] 父进程<%s>' % (os.getpid(), os.getppid())) 7 time.sleep(300) 8 9 10 if __name__ == '__main__': 11 p = Process(target=task) 12 p.start() 13 print('主', os.getpid(), os.getppid()) 14 time.sleep(1000)
终端打印:
进程对象其他相关的属性或方法
p.name 更改子进程的名字
1 from multiprocessing import Process 2 import time, os 3 4 5 def task(): 6 print('%s is running' % os.getppid()) 7 time.sleep(300) 8 9 10 if __name__ == '__main__': 11 p = Process(target=task, name='子进程1') 12 p.start() 13 print(p.name) 14 print('主') 15 time.sleep(1000)
终端打印:
terminate与is_alive
p.terminate() 关闭进程
p.is_alive() 查看进程是否存活
1 from multiprocessing import Process 2 import time, os 3 4 5 def task(): 6 print('%s is running' % os.getppid()) 7 time.sleep(300) 8 9 10 if __name__ == '__main__': 11 p = Process(target=task, name='子进程1') 12 p.start() 13 p.terminate() 14 time.sleep(0.1) 15 print(p.is_alive()) 16 print('主')
终端打印: