进程
一、进程
概念:一个正在运行的程序或者软件就是一个进程,它是操作系统进行资源分配的基本单位,每启动一个进程操作系统都会给其中分配一定的运行资源保证进程的运行。
注意:一个程序运行后至少有一个进程,一个进程默认有一个线程,进程里面可以创建多个线程,线程是依附在进程里面的,没有进程就没有线程
import multiprocessing
import os
import time
def process_1(name, age):
for i in range(5):
print("我是进程一,{}今年{}岁".format(name, age))
print("子的进程:{},进程编号:{},父亲编号:{}".format(multiprocessing.current_process(), os.getpid(), os.getppid()))
time.sleep(0.1)
def process_2(name, age):
for i in range(5):
print("我是进程二,{}今年{}岁".format(name, age))
print("子的进程:{},进程编号:{},父亲编号:{}".format(multiprocessing.current_process(), os.getpid(), os.getppid()))
time.sleep(0.1)
if __name__ == '__main__':
process_1_target = multiprocessing.Process(target=process_1, name="第一个子进程", args=("小明",), kwargs={"age": 20})
process_2_target = multiprocessing.Process(target=process_2, name="第二个子进程", args=("小花",), kwargs={"age": 30})
process_1_target.start()
process_2_target.start()
print("主的进程:{},进程编号:{},父亲编号:{}".format(multiprocessing.current_process(), os.getpid(), os.getppid()))
-
multiprocessing.Process(进程初始化)
-
target=process_1:子进程的任务
-
name=“第一个子进程”:子进程的名字
-
args=(“小明”,):元祖传参
-
kwargs={“age”: 20}:字典传参
-
-
process_1_target.start():开启任务
拓展:
-
os.getpid():获取当前进程pid
-
os.getppid():获取当前父进程pid
-
os.kill(os.getpid(), 9):根据进程号,杀死指定进程
-
process_1_target.join():则会等待子进程结束,主进程才继续往下执行
-
process_1_target.terminate(): 主动让子进程销毁结束
-
守护进程
-
默认守护进程为False,即主进程开启的子进程都是非守护进程,所以当主进程代码运行完,会等待子进程跑完,才会结束
process_2_target.daemon=True process_2_target.start()
这样设置为True,则会开启守护进程,只要主进程结束,则子进程则会跟随销毁
-
注意:进程之间不共享全局变量
import multiprocessing
import time
globals_list = list()
def process_1():
for i in range(5):
global globals_list
globals_list.append(i)
time.sleep(0.1)
print("子进程1的列表:", globals_list)
def process_2():
global globals_list
print("子进程2的列表:", globals_list)
if __name__ == '__main__':
process_1_target = multiprocessing.Process(target=process_1)
process_2_target = multiprocessing.Process(target=process_2)
process_1_target.start()
process_1_target.join()
process_2_target.start()
process_2_target.join()
print("主进程的列表:", globals_list)
二、进程之间的通信-Queue
q = multiprocessing.Queue():
初始化Queue()对象时(例如:q=Queue()),若括号中没有指定最大可接收的消息数量,或数量为负值,那么就代表可接受的消息数量没有上限(直到内存的尽头);
-
Queue.qsize():返回当前队列包含的消息数量;
-
Queue.empty():如果队列为空,返回True,反之False ;
-
Queue.full():如果队列满了,返回True,反之False;
-
Queue.get([block[, timeout]]):获取队列中的一条消息,然后将其从列队中移除,block默认值为True;
1)如果block使用默认值,且没有设置timeout(单位秒),消息列队如果为空,此时程序将被阻塞(停在读取状态),直到从消息列队读到消息为止,如果设置了timeout,则会等待timeout秒,若还没读取到任何消息,则抛出"Queue.Empty"异常;
2)如果block值为False,消息列队如果为空,则会立刻抛出"Queue.Empty"异常;
-
Queue.get_nowait():相当Queue.get(False);
-
Queue.put(item,[block[, timeout]]):将item消息写入队列,block默认值为True;
1)如果block使用默认值,且没有设置timeout(单位秒),消息列队如果已经没有空间可写入,此时程序将被阻塞(停在写入状态),直到从消息列队腾出空间为止,如果设置了timeout,则会等待timeout秒,若还没空间,则抛出"Queue.Full"异常;
2)如果block值为False,消息列队如果没有空间可写入,则会立刻抛出"Queue.Full"异常;
-
Queue.put_nowait(item):相当Queue.put(item, False);
import multiprocessing
import time
def process_1(q):
for i in range(5):
print("保存到队列的值:{}".format(i))
q.put(i)
time.sleep(0.1)
def process_2(q):
while not q.empty():
print("读取到的值:{}".format(q.get()))
time.sleep(0.1)
if __name__ == '__main__':
q = multiprocessing.Queue()
process_1_target = multiprocessing.Process(target=process_1,args=(q,))
process_2_target = multiprocessing.Process(target=process_2,args=(q,))
process_1_target.start()
process_1_target.join()
process_2_target.start()
三、进程池以及进程池通信
进程池
初始化Pool时,可以指定一个最大进程数,当有新的请求提交到Pool中时,如果池还没有满,那么就会创建一个新的进程用来执行该请求;但如果池中的进程数已经达到指定的最大值,那么该请求就会等待,直到池中有进程结束,才会用之前的进程来执行新的任务
import multiprocessing
import os
import random
import time
def process_1(i):
print("第{}号开始执行,进程数{}".format(i, os.getpid()))
time.sleep(random.random() * 3)
print("第{}号执行完成".format(os.getpid()))
if __name__ == '__main__':
# 创建一个进程池,里面有三个进程在循环使用
po = multiprocessing.Pool(3)
for i in range(0, 10):
po.apply_async(process_1, (i,))
# 关闭进程池
po.close()
# 等待进程池所有任务执行完成
po.join()
multiprocessing.Pool常用函数解析:
- apply_async(func[, args[, kwds]]) :使用非阻塞方式调用func(并行执行,堵塞方式必须等待上一个进程退出才能执行下一个进程),args为传递给func的参数列表,kwds为传递给func的关键字参数列表;
- close():关闭Pool,使其不再接受新的任务;
- terminate():不管任务是否完成,立即终止;
- join():主进程阻塞,等待子进程的退出, 必须在close或terminate之后使用;
进程池通信
注意:如果要使用Pool创建进程,就需要使用multiprocessing.Manager()中的Queue(),而不是multiprocessing.Queue()
import multiprocessing
import random
import time
def process_1(q, i):
q.put(i)
time.sleep(random.random() * 3)
def process_2(q):
while not q.empty():
print(q.get())
time.sleep(random.random() * 3)
if __name__ == '__main__':
q = multiprocessing.Manager().Queue()
po = multiprocessing.Pool(3)
for i in range(0, 10):
po.apply_async(process_1, (q, i))
time.sleep(1)
po.apply_async(process_2, (q,))
# 关闭进程池
po.close()
# 等待进程池所有任务执行完成
po.join()