进程概念
进程
- 进程是程序的一次执行过程,是一个动态概念,是程序在执行过程中分配和管理资源的基本单位,每一个进程都有一个自己的地址空间,至少有 5 种基本状态,它们是:初始态,执行态,等待状态,就绪状态,终止状态。
- 例如每打开一个软件,或者每执行一个python脚本都是启动一个进程
- 启动进程会占用cpu和内存
多进程
- 就是同时启动多个软件(进程)
- 例如手机系统启动多个软件,手机系统属于主进程,启动的多个软件属于子进程
- 多个进程同时在执行程序时,他们之间互不干扰,各自执行自己的业务逻辑
进程的创建模块:模块multiprocessing的Process类
创建进程:
from multiprocessing import Process
p = Process(target,args,kwargs,name,group)
或者:
import multiprocessing
p = multiprocessing.Process(target,args,kwargs,name,group)
参数:
- target:表示这个进程实例所调用对象;
- args:表示调用对象的位置参数元组;
- kwargs:表示调用对象的关键字参数字典;
- name:为当前进程实例的别名;
- group:大多数情况下用不到;
创建进程的2种方式
方式1:通过Process类可以创建一个进程对象,然后使用start开启进程
import os
import multiprocessing
def test1():
print(f'test1,进程号是:{os.getpid()}')
def test2(name, age, like):
print(f'test2,name={name},age={age},like={like},进程号是:{os.getpid()}')
if __name__ == '__main__':
t1 = multiprocessing.Process(target=test1)
t1.start()
t2 = multiprocessing.Process(target=test2, args=('张三', 18, '跑步'))
t2.start()
结果:
方式2:
通过子类继承Process类,子类中必须有run方法,里面实现进程功能
创建实例化对象后,调用对象的start方法,会执行run中的代码
import os
from multiprocessing import Process
class Test(Process):
# 因为Process类本身也有__init__方法,这个子类相当于重写了这个方法,
# 但这样就会带来一个问题,我们并没有完全的初始化一个Process类,所以就不能使用从这个类继承的一些方法和属性,
# 最好的方法就是将继承类本身传递给Process.__init__方法,完成这些初始化操作
def __init__(self, name, age, like):
Process.__init__(self)
self.name = name
self.age = age
self.like = like
def run(self):
print(f'name={self.name},age={self.age},like={self.like},进程号是:{os.getpid()}')
if __name__ == '__main__':
t = Test('张三', 18, '跑步')
t.start()
结果:
Process类常用方法
- start():启动进程,并调用该子进程中的p.run()
- run():进程启动进运行的方法,就是它去调用target指定的函数,我们自定义类的类中一定要实现该方法。
- terminate():强制终止进程。不会进行任何清理操作,如果p创建了子进程,该子进程就成了僵尸进程,使用此方法需要小心:如果此进
- 还保存了一个锁那么也将不会释放这个锁,进而导致死锁。
- is_alive():判断进程是否是“活着”的状态。
- join(timeout):让主线程等待某一子进程结束,才继续执行主进程。timeout是可选的超时时间。超过一个时间主进程就不等待了。
- kill():终止当前进程,使其立即退出
多进程的问题:
- 通过进程模块执行的函数无法获取返回值
- 多个进程同时修改文件可能会出现错误
- 进程数量太多可能会造成资源不足,甚至死机等情况
注:
- os.getpid():获取当前进程id
- os.getppid():获取父进程id
例1:使用单进程
import os
import time
def test1():
for i in range(3):
print(f'a={i},进程号是:{os.getpid()}')
time.sleep(1)
def test2():
for i in range(3):
print(f'b={i},进程号是:{os.getpid()}')
time.sleep(1)
if __name__ == '__main__':
# 开始时间
start_time = time.time()
test1()
test2()
# 结束时间
now_time = time.time()
# 时间间隔
time = now_time - start_time
print(f'时间间隔:{time},进程号是:{os.getpid()}')
结果:进程号始终都是5628,说明是单进程执行的,所以最后的间隔时间是6s左右
例2:函数test1创建一个进程
import os
import time
import multiprocessing
def test1():
for i in range(3):
print(f'test1={i},进程号是:{os.getpid()}')
time.sleep(1)
def test2():
for i in range(3):
print(f'test2={i},进程号是:{os.getpid()}')
time.sleep(1)
if __name__ == '__main__':
# 开始时间
start_time = time.time()
# 创建一个线程
a = multiprocessing.Process(target=test1)
# 开启线程
a.start()
test2()
# 结束时间
now_time = time.time()
# 时间间隔
time = now_time - start_time
print(f'时间间隔:{time},进程号是:{os.getpid()}')
结果:
- 进程16368执行了开始时间、test2函数、结束时间、最后打印print
- 进程9327执行了test1函数
- 这2个进程是同时执行的,所以最后的的间隔时间大概是3s
例3:2个函数分别设置进程
import os
import time
import multiprocessing
def test1():
for i in range(3):
print(f'test1={i},进程号是:{os.getpid()}')
time.sleep(1)
def test2():
for i in range(3):
print(f'test2={i},进程号是:{os.getpid()}')
time.sleep(1)
if __name__ == '__main__':
# 开始时间
start_time = time.time()
# 创建2个进程
a = multiprocessing.Process(target=test1)
b = multiprocessing.Process(target=test2)
# 执行进程a和b
for i in (a, b):
i.start()
# 结束时间
now_time = time.time()
# 时间间隔
time = now_time - start_time
print(f'时间间隔:{time},进程号是:{os.getpid()}')
结果:
- 进程15960执行了开始时间和结束时间,以及最后的打印时间间隔
- 进程9488执行了test1函数
- 进程16616执行了test2函数
- 这3个进程是同时执行的,所以打印的时间接近0s
例4:阻塞其中一个子进程,等待它执行结束后再执行其他的
import os
import time
import multiprocessing
def test1():
for i in range(3):
print(f'test1={i},进程号是:{os.getpid()}')
time.sleep(1)
def test2():
for i in range(3):
print(f'test2={i},进程号是:{os.getpid()}')
time.sleep(1)
if __name__ == '__main__':
# 开始时间
start_time = time.time()
# 创建进程
a = multiprocessing.Process(target=test1)
# 执行进程
a.start()
# 阻塞进程
a.join()
b = multiprocessing.Process(target=test2)
b.start()
# 结束时间
now_time = time.time()
# 时间间隔
time = now_time - start_time
print(f'时间间隔:{time},进程号是:{os.getpid()}')
结果:
- 进程5152执行了test1函数
- 进程4428和进程16136是在进程5152执行结束后才开始同时执行的
例5:阻塞2个进程,等待他们执行结束后再执行其他的
import os
import time
import multiprocessing
def test1():
for i in range(3):
print(f'test1={i},进程号是:{os.getpid()}')
time.sleep(1)
def test2():
for i in range(3):
print(f'test2={i},进程号是:{os.getpid()}')
time.sleep(1)
if __name__ == '__main__':
# 开始时间
start_time = time.time()
# 创建一个线程
a = multiprocessing.Process(target=test1)
b = multiprocessing.Process(target=test2)
# 同时开始执行2个子进程
for i in (a, b):
i.start()
# 阻塞2个进程
for j in (a, b):
i.join()
# 结束时间
now_time = time.time()
# 时间间隔
time = now_time - start_time
print(f'时间间隔:{time},进程号是:{os.getpid()}')
结果:
- 进程576和进程14596是同时执行的
- 2个子进程执行结束后才开始执行进程10744
例6:杀死一个进程
import os
import time
import multiprocessing
def test1():
for i in range(3):
print(f'test1={i},进程号是:{os.getpid()}')
time.sleep(1)
def test2():
for i in range(3):
print(f'test2={i},进程号是:{os.getpid()}')
time.sleep(1)
if __name__ == '__main__':
# 开始时间
start_time = time.time()
# 创建一个线程
a = multiprocessing.Process(target=test1)
b = multiprocessing.Process(target=test2)
# 同时开始执行2个子进程
for i in (a, b):
i.start()
# 杀死进程
a.kill()
# 结束时间
now_time = time.time()
# 时间间隔
time = now_time - start_time
print(f'时间间隔:{time},进程号是:{os.getpid()}')
结果:
- 执行test1的进程被杀死,没有执行