Python多进程

发布时间 2023-09-23 16:48:32作者: donfag

一、multiprocessing模块提供了一个创建进程的类Process,其创建进程有两种方法:
1、创建一个Process类的实例,并指定目任务函数:
示例代码:

 1 from multiprocessing import Process
 2 import os
 3 import time
 4 
 5 def task_process(delay):
 6     num = 0
 7     for i in range(delay*100000000):
 8         num += 1
 9     print(f"进程pid为{os.getpid()},执行完成")
10 
11 if __name__ == '__main__':
12     print(f"父进程pid为:{os.getpid()}")
13     t0 = time.time()
14     task_process(3)
15     task_process(3)
16     t1 = time.time()
17     print(f"顺序执行耗时{t1-t0}")
18     p0 = Process(target=task_process,args=(3,))
19     p1 = Process(target=task_process, args=(3,))
20     t2 = time.time()
21     p0.start();p1.start()
22     p0.join();p1.join()
23     t3 = time.time()
24     print(f"多进程并发执行耗时{t3-t2}")

返回内容:
父进程pid为:13008
进程pid为13008,执行完成
进程pid为13008,执行完成
顺序执行耗时48.99575757980347
进程pid为13784,执行完成
进程pid为6468,执行完成
多进程并发执行耗时32.62778663635254

2、自定义一个类并继承Process类,重写其__init__()方法和run()方法:
示例代码:

 1 from multiprocessing import Process
 2 import os
 3 import time
 4 
 5 class MyProcess(Process):
 6     def __init__(self,delay):
 7         self.delay = delay
 8         super().__init__()
 9     def run(self):
10         num = 0
11         for i in range(self.delay * 100000000):
12             num += 1
13         print(f"进程pid为{os.getpid()},执行皮完成")
14 
15 if __name__ == '__main__':
16     print(f"父进程pid为:{os.getpid()}")
17     p0 = MyProcess(3)
18     p1 = MyProcess(3)
19     t0 = time.time()
20     p0.start();p1.start()
21     p0.join();p1.join()
22     t1 = time.time()
23     print(f"多进程并发执行耗时{t1-t0}")

返回内容:
父进程pid为:6784
进程pid为14164,执行皮完成
进程pid为7128,执行皮完成
多进程并发执行耗时34.326029539108276

二、进程并发控制这Semaphore
Semaphore用来控制对共享资源的访问数量,可以控制同一时刻并发的进程数。
示例代码:

 1 import multiprocessing,time
 2 def worker(s,i):
 3     s.acquire()
 4     print(time.strftime('%H:%M:%S'),multiprocessing.current_process().name+" 获得运行锁")
 5     time.sleep(i)
 6     print(time.strftime('%H:%M:%S'), multiprocessing.current_process().name + " 释放运行锁")
 7     s.release()
 8 
 9 if __name__ == "__main__":
10     s = multiprocessing.Semaphore(2) #同一时刻只有两个进程在执行操作
11     for i in range(6):
12         p = multiprocessing.Process(target=worker,args=(s,2))
13         p.start()

运行结果:
15:26:12 Process-1 获得运行锁
15:26:12 Process-2 获得运行锁
15:26:14 Process-1 释放运行锁
15:26:14 Process-2 释放运行锁
15:26:14 Process-5 获得运行锁
15:26:14 Process-3 获得运行锁
15:26:16 Process-5 释放运行锁
15:26:16 Process-3 释放运行锁
15:26:16 Process-4 获得运行锁
15:26:16 Process-6 获得运行锁
15:26:18 Process-4 释放运行锁
15:26:18 Process-6 释放运行锁

三、进程同步这Lock:
多进程目的是并发执行,提高资源利用率,从而提高效率,但有时候我们需要在某一时间只能有一个进程访问某个共享资源的话,就需要使用锁Lock.
示例代码一,不加锁:

 1 import multiprocessing,time
 2 def task1():
 3     n = 5
 4     while n > 1:
 5         print(f"{time.strftime('%H:%M:%S')} task1 输出信息")
 6         time.sleep(1)
 7         n -= 1
 8 
 9 def task2():
10     n = 5
11     while n > 1:
12         print(f"{time.strftime('%H:%M:%S')} task2 输出信息")
13         time.sleep(1)
14         n -= 1
15 
16 def task3():
17     n = 5
18     while n > 1:
19         print(f"{time.strftime('%H:%M:%S')} task3 输出信息")
20         time.sleep(1)
21         n -= 1
22 
23 if __name__ == "__main__":
24     p1 = multiprocessing.Process(target=task1)
25     p2 = multiprocessing.Process(target=task2)
26     p3 = multiprocessing.Process(target=task3)
27     p1.start()
28     p2.start()
29     p3.start()

返回结果:
15:43:47 task1 输出信息
15:43:47 task2 输出信息
15:43:47 task3 输出信息
15:43:48 task1 输出信息
15:43:48 task2 输出信息
15:43:48 task3 输出信息
15:43:49 task1 输出信息
15:43:49 task2 输出信息
15:43:49 task3 输出信息
15:43:50 task1 输出信息
15:43:50 task2 输出信息
15:43:50 task3 输出信息
从返回结果可以看出,同一时刻有两个或三个进程在运行,如果需要同一时刻只允许一个进程运行,可以改成一面的代码:
示例代码二,加锁:

 1 import multiprocessing,time
 2 def task1(lock):
 3     with lock: #和下文的lock.acquire()同样
 4         n = 5
 5         while n > 1:
 6             print(f"{time.strftime('%H:%M:%S')} task1 输出信息")
 7             time.sleep(1)
 8             n -= 1
 9 
10 def task2(lock):
11     lock.acquire()
12     n = 5
13     while n > 1:
14         print(f"{time.strftime('%H:%M:%S')} task2 输出信息")
15         time.sleep(1)
16         n -= 1
17     lock.release()
18 
19 def task3(lock):
20     lock.acquire()
21     n = 5
22     while n > 1:
23         print(f"{time.strftime('%H:%M:%S')} task3 输出信息")
24         time.sleep(1)
25         n -= 1
26     lock.release()
27 if __name__ == "__main__":
28     lock = multiprocessing.Lock()
29     p1 = multiprocessing.Process(target=task1,args=(lock,))
30     p2 = multiprocessing.Process(target=task2,args=(lock,))
31     p3 = multiprocessing.Process(target=task3,args=(lock,))
32     p1.start()
33     p2.start()
34     p3.start()

返回结果:
15:51:03 task1 输出信息
15:51:04 task1 输出信息
15:51:05 task1 输出信息
15:51:06 task1 输出信息
15:51:07 task2 输出信息
15:51:08 task2 输出信息
15:51:09 task2 输出信息
15:51:10 task2 输出信息
15:51:11 task3 输出信息
15:51:12 task3 输出信息
15:51:13 task3 输出信息
15:51:14 task3 输出信息
从结要可以看出同一时刻,只有一个进程在运行。

四、进程同步之Event:
Event是用来实现进程之间同步通信的:
示例代码:

 1 import multiprocessing,time
 2 
 3 def wait_for_event(e):
 4     e.wait()
 5     time.sleep(1)
 6     #唤醒后清除Event状态,为后续继续等待
 7     e.clear()
 8     print(f"{time.strftime('%H:%M:%S')} 进程 A:我们是兄弟,我等你...")
 9     e.wait()
10     print(f"{time.strftime('%H:%M:%S')} 进程 A:好的,是兄弟一起走")
11 def wait_for_event_timeout(e,t):
12     e.wait()
13     time.sleep(1)
14     # 唤醒后清除Event状态,为后续继续等待
15     e.clear()
16     print(f"{time.strftime('%H:%M:%S')} 进程 B:好吧,我最多等你{t}秒")
17     e.wait(t)
18     print(f"{time.strftime('%H:%M:%S')} 进程 B:{t}秒时间到,我继续往前走了")
19 if __name__ == "__main__":
20     e = multiprocessing.Event()
21     w1 = multiprocessing.Process(target=wait_for_event,args=(e,))
22     w2 = multiprocessing.Process(target=wait_for_event_timeout, args=(e,5))
23     w1.start()
24     w2.start()
25     #主进程发话:
26     print(f"{time.strftime('%H:%M:%S')} 主进程:谁等我下,我需要8s时间")
27     #唤醒进程:
28     e.set()
29     time.sleep(8)
30     print(f"{time.strftime('%H:%M:%S')} 主进程:好了,我赶上了")
31     #再次唤醒等待的进程:
32     e.set()
33     w1.join()
34     w2.join()
35     print(f"{time.strftime('%H:%M:%S')} 主进程:退出")

返回结果:
16:21:05 主进程:谁等我下,我需要8s时间
16:21:06 进程 A:我们是兄弟,我等你...
16:21:06 进程 B:好吧,我最多等你5秒
16:21:11 进程 B:5秒时间到,我继续往前走了
16:21:13 主进程:好了,我赶上了
16:21:13 进程 A:好的,是兄弟一起走
16:21:13 主进程:退出

以上内容来自郑征的《Python自动化运维快速入门》,清华大学出版社。