python 多进程

什么是进程

参考任务管理器,所有任务都是进程

线程包含在进程之内。

 

一个程序运行起来后,代码 + 用到的资源称之为进程

它是操作系统分配资源的基本单元。

不仅可以通过线程完成多任务,进程同样也可以做到。

进程的状态

工作中,任务数往往大于cpu的核心数。即,一定会有一些任务在执行,而另一些在等待cpu进行执行,因此产生了不同的状态。

就绪状态

运行条件都已满足,在等待cpu执行

执行状态

cpu正在执行其功能

等待状态

等待满足某些条件,例如一个程序sleep了,此时就处于等待状态

 

多进程

多进程可以做到并行,而多线程不行

multiprocessing模块

使用多进程要用到该模块。

Process 创建参数设置

target 如果传递了函数的引用,可以创建进程任务

args 给target指定的函数传递的参数,元祖的方式传参数

kwargs 给target指定的函数命名传参

name 给进程设定一个名字,可以不设置

group 指定进程组,到时候用不到

 

process 创建实例对象的常用方法

start() 启动,创建子进程

is_alive() 判断进程是否存活

join(timeout) 是否等待子进程执行结束,或者等待多少秒

terminate() 不管任务是否完成逻辑终止子进程

代码实例

 1 from multiprocessing import Process
 2 import time
 3 num =100
 4 
 5 def work1():
 6    for i in range(10):
 7       global  num
 8       print(F"这个是任务1------{num}")
 9       num += 1
10       time.sleep(0.5)
11 def work2():
12    for i in range(10):
13       global num
14       print(F"这个是任务2------{num}")
15       num += 1
16       time.sleep(0.5)
17 # 创建两个进程
18 if __name__ == '__main__':
19    # 进程执行的时候不加 __name__ == main 会报错
20    # 原因是什么呢?
21    # 如果没有main ,代码会相当于,从模块导入,会陷入无限递归的状态
22    # 进程之间的资源是独立的, windows下面会报错, linux mac 不会
23    # 全局变量不进行共享,不会造成数据不安全之类的问题
24    p1 = Process(target=work1)
25    p2 = Process(target=work2)
26    p1.start()
27    p2.start()

个人理解

运行一个进程的时候,系统会划分出来一块内存,存储这个进程的相关资源

属于该进程的线程是会使用进程的相关资源的,在进程的内存块中划出小块内存支持线程运行。

进程间全局变量则不共享,原因是因为使用的并非是同一块内存地址。

 

进程,线程之间的区别联系

线程存在于进程之中

进程间存在于不同的内存地址中,进程之间全局变量不共享。

那么如果想要共享,实现进程间的通讯问题。

则需要使用到多进程模块下的队列。

 

前面学到的queue模块,虽然是线程安全的,但不适用于多进程

需要使用的事multiprocessing下的Queue模块

量模块在内置方法上没什么区别,但是多进程中的queue更为强大、。

 

区别为Queue是各子进程私有,multiprocessing.Queue是各子进程共有。

看一下代码实例

def work1(q):
   while True:
      if q.qsize() > 0 :
         url = q.get()
         requests.get(url)
         print("work1 正在执行任务----")
def work2(q):
   while True:
      if q.qsize() > 0:
         url = q.get()
         requests.get(url)
         print("work2 正在执行任务----")
if __name__ == '__main__':
   # 进程执行的时候不加 __name__ == main 会报错
   # 原因是什么呢?
   # 如果没有main ,代码会相当于,从模块导入,会陷入无限递归的状态
   # 进程之间的资源是独立的, windows下面会报错, linux mac 不会
   # 全局变量不进行共享,不会造成数据不安全之类的问题

   # 注意!!! 如果吧队列放到全局变量中,就依然不会行程进程之间资源共享
   # 原因跟之前没有加main是一样的,
   q =Queue()
   # 通过多进程下面的queue,然后穿参数进去,然后进程之间共同享有queue资源
   for i in range(10):
      q.put("http://www.baidu.com")
   p1 = Process(target=work1,args=(q,))
   p2 = Process(target=work2,args=(q,))
   p1.start()
   p2.start()

进程池子

当需要创新的子进程数量不多时,利用multiprocessing中的process动态生成多个线程。

但是如果上百甚至上千个目标,手动去创建进程的工作量太大。

此时可以使用multiprocessing模块提供的pool方法。

 

初始化pool时,可以指定一个最大的进程数,当有新的请求提交到pool中时

如果池子还没满,那么就会创建一个新的进程用来执行该请求,

但是如果进程池内数量已达到最大,

那么请求就会等待,等到池中有进程结束,才会用之前的进程来执行新任务。

pool的方法

 1 apply_async() 使用非租塞方式调用func
 2 close() 关闭pool
 3 terminate() 不管任务是否完成立即终止
 4 join() 主进程阻塞,等待子进程的退出,必须在close或terminate之后使用
 5 import os
 6 import time
 7 from multiprocessing import Process,Queue,Manager,Pool
 8 def work1():
 9   print("进程池---{}".format(os.getpid()))
10   time.sleep(1)
11 if __name__ == '__main__':
12 p = Pool(3)
13 for i in range(10):
14   p.apply_async(work1)
15 
16 p.close()
17 p.join()

pool中的queue

如果使用pool创建进程,就需要用multiprocessing,manager()中的queue()

 1 例子:
 2 import os
 3 import time
 4 from multiprocessing import Pool,Manager
 5 
 6 def work1(q):
 7   print("进程池---{}".format(os.getpid()))
 8   print(q.get())
 9   time.sleep(1)
10 if __name__ == '__main__':
11 Manager()
12 q = Manager().Queue()
13 for i in range(10):
14   q.put("你好啊")
15 p = Pool(3)
16 for i in range(10):
17   p.apply_async(work1)
18 p.close()
19 p.join()

 

原文地址:https://www.cnblogs.com/addicated/p/13175336.html