Python 多进程编程(一)Pool Manager in multiprocessing
- 子进程的复制范围:pool.apply_async产生的新进程会复制主进程里不在if name == 'main’里定义的代码和数据,然后运行传入的func函数。
- 两个进程同步的变量:因为新进程里的代码和数据是复制出来的,因此在两个进程中对两者进行更新并不会相互更新。Manager就是为了保证同一个变量在一个进程中跟新了,另一个进程中也跟着响应的更新了。
- 为了保证同步更新的,有时候需要引入Lock来保证操作的原子性。
使用multiprocessing的时候需要注意的几个问题是
- 由于上面说的子进程的复制范围:传入pool.apply_async 的函数func,必须是在if name == 'main’外定义的 函数 或者 类的成员函数
- 同样,如果代码写在if name == 'main’外,则会被子进程运行,因此如果在if name == 'main’外调用pool.apply_async,则会无限递归的产生子进程而报错。
- 最后,很多时候多进程代码报错了,但报错信息却没有打印到控制台,此时需要给代码加上try except,把可能的报错信息写入文件。
示例代码如下:
import multiprocessing
import time
def f(i, norm_list, manager_list, n):
time.sleep(3)
norm_list.append(n)
manager_list.append(n)
print(f"{i}-th process, normal_list", norm_list)
print(f"{i}-th process, manager_list", manager_list)
if __name__ == '__main__':
m = multiprocessing.Manager()
p = multiprocessing.Pool(3)
a_list = list(range(4))
m_dict = m.dict()
m_list = m.list(a_list)
p_list = []
for i in range(3):
# the args passed to new process is simple copy if not variable of manager
p.apply_async(f, args=(i, a_list, m_list, i))
time.sleep(2) # make sure sub process have created and run. after sub process run, modify a_list and m_list
a_list.append("a")
m_list.append("a")
p.close()
p.join()
print(a_list)
print(m_list)
输出
0-th process, normal_list [0, 1, 2, 3, 0]
0-th process, manager_list [0, 1, 2, 3, 'a', 0, 1]
1-th process, normal_list [0, 1, 2, 3, 1]
1-th process, manager_list [0, 1, 2, 3, 'a', 0, 1]
2-th process, normal_list [0, 1, 2, 3, 2]
2-th process, manager_list [0, 1, 2, 3, 'a', 0, 1, 2]
[0, 1, 2, 3, 'a']
[0, 1, 2, 3, 'a', 0, 1, 2]