主进程是在子进程执行完毕之后才结束的,主进程回收子进程资源
p.join() 阻塞,直到p对应的子进程对象执行结束
from multiprocessing import Process
import time
import os
def son_process():
print('start son', os.getpid())
time.sleep(3)
print('end son')
if __name__ == '__main__':
p = Process(target=son_process)
p.start()
p.join() # 阻塞,直到p对应的子进程对象执行结束
print('所有任务结束')
# start son 7164
# end son
# 所有任务结束
守护进程(daemon)
-
p.daemon = True 将当前的子进程设置为守护进程
守护进程会随着父进程的代码结束而结束
正常情况下 父进程永远会等着子进程结束
如果设置了守护进程 父进程的代码结束之后 守护进程也跟着结束
from multiprocessing import Process
import time
def son():
while True:
time.sleep(1)
print('in son')
if __name__ == '__main__':
p = Process(target=son)
p.daemon = True # 将当前的子进程设置为守护进程
p.start()
time.sleep(5)
偏要守护进程在子进程结束之后才结束
from multiprocessing import Process
import time
def son():
while True:
time.sleep(1)
print('in son')
def son2():
print('start son2')
time.sleep(10)
printt('end son2')
if __name__ == '__main__':
p = Process(target=son)
p.daemon = True
p.start()
p = Process(target=son2).start()
time.sleep(5)
p.join()
子进程结束之后,父进程才会结束
代码结束和进程结束是两回事
-
没设置守护进程:
-
1.子进程的代码和主进程的代码自己执行自己的,互相之间没有联系
-
2.如果主进程的代码先结束,主进程不结束,等子进程代码结束,回收子进程的资源,主进程才会结束
-
3.如果子进程先结束,主进程边回收子进程的资源边执行自己的代码,当代码和资源都回收完毕,主进程才会结束
-
-
设置了守护进程
-
1.子进程的代码和主进程的代码自己执行自己的,互相之间没有关系
-
2.一旦主进程的代码先结束,主进程会结束掉子进程(也就是守护进程),然后回收资源,然后主进程才结束
-
守护进程只守护主进程代码,守护进程不会守护除了主进程代码之外的其他子进程
from multuprocessing import Process
import time
def son()
while True:
time.sleep(1)
print('in son')
def son2():
print('start son2')
time.sleep(10)
print('end son2')
if __name__ == '__main__':
p = Process(target=son)
p.daemon = True
p.start()
Process(target=son2).start()
time.sleep(5)
Process对象的方法
p.start() # 开启进程(相当于告诉操作系统要开启一个子进程,而子进程的调度是由操作系统控制的)
p.join() # 阻塞,直到p对应的子进程结束(如果执行这句话之前子进程就结束了,那么主进程就不阻塞了)
p.terminate() # 异步结束子进程(异步非阻塞操作)
p.is__alive() # 判断进程实例是否还在运行
面向对象的方式开启进程
class MyProcess(Process):
def run(self):
print('son',os.getpid())
if __name__ == '__main__':
print('father',os.getpid())
p = MyProcess()
p.start()
传参数
class MyProcess(Process):
def __init__(self,arg1,arg2):
self.arg1 = arg1
self.arg2 = arg2
def run(self):
print(self.arg1,self.arg2)
if __name__ == '__main__':
print('father',os.getpid())
p = MyProcess(1,2)
p = start()
数据安全(锁)
锁:用来保证数据安全
如果多个进程同时对一个文件进行操作会出现什么问题
-
1.读数据:可以同时读
-
2.写数据:但不可以同时写
Lock
from multiprocessing import Process,Lock
def change(lock):
print('本是青灯不归客\n一部分并发的代码,多个进程之间互相不干扰的执行着')
lock.acquire()
with open('file','r')as f:
content = f.read()
num = int(content)
num += 1
with open('file','w')as f:
f.write(str(num))
lock.release()
print('却因浊酒留红尘\n另一部分并发的代码,多个进程之间互相不干扰的执行着')
if __name__ == '__main__':
lock = Lock()
p = Process(target=change,args=(lock,))
p.start()
# 当多个进程同时操作文件/共享的一些数据的时候就会出现数据不安全
# 开启多进程 同时执行多行代码
# 其中20行涉及到了操作同一个文件
# 只给这20行代码加锁,来保证数据的安全
进程之间的通信IPC -- 队列
Inter Process Communication
from multiprocessing import Queue,Process
def son(q):
print(q.get())
if __name__ == '__main__':
q = Queue()
p = Process(target=son,args=(q,))
p = start()
q.put(0)
在进程之间是维护数据的安全 -- 进程安全
队列是进程安全的(进程队列保证了进程的数据安全)
队列都是先进先出
队列是基于文件+锁实现的
队列一共提供了两个方法:get/put
# q = Queue(2) # 只能放两个
# q.put({1,2,3})
# q.put({1,2,3})
# q.put({1,2,3}) # put 是一个同步阻塞方法,会阻塞直到队列不满
# q = Queue(2)
# try:
# for i in range(4):
# q.put_nowait(i) # put_nowait 同步阻塞方法
# except queue.Full:
# print(i)
# q = Queue(5)
# ret = q.qsize() # 查看当前队列有多少值
# print(ret)
# print(q.empty())
# print(q.full())
队列Queue = 管道Pipe + 锁
Pipe 基于文件实现的(socket+pickle)= 数据不安全
Queue 基于文件(socket+pickle)+ 锁(lock)实现的 = 数据安全
基于Pipe+锁(lock)实现的
IPC:
-
内置模块实现的机制:队列/管道
-
第三方工具:redis rabbitMQ memcache
打印进度
import time
for i in range(101):
print('\r当前的进度:%.2f%%'%i,end="")
time.sleep(0.05)