Python多进程执行时出现意外重复打印问题排查
Python多进程中__name__相关重复打印问题解答
文件代码
1. 测试文件
print('Before entering name==main') if __name__=="__main__": from library.poc.name_main.name_main_2 import do_operate1 print('Condition satisfied.') x = [9,8,7,6,5,4,3,2] y = [10,9,8,7,6,5,4,3] result = do_operate1(x,y) print('result of do add on',x,'and',y,':',result, 'validate', sum(x) + sum(y)) else: print('No condition satisfied.',__name__)
2. do_operate文件
def do_operate1(x_list,y_list): tuple_value_list = [] # for i,j in it.chain(range(1,x+1), range(1,y+1)): for i, j in zip(x_list,y_list): tuple_value = (i,j) # print(i,j) tuple_value_list.append(tuple_value) if len(x_list) < 7: cpu_count = len(x_list) elif len(x_list) >= 7: cpu_count = 7 pool = multiprocessing.Pool(cpu_count) sum_val = 0 for result in pool.starmap(do_add, tuple_value_list): sum_val = sum_val + result pool.close() return sum_val
3. do_add文件
import time # main function def do_add(x,y): time.sleep(x+y) print('Input x',x,'and y',y,'result', x+y) return x + y
执行输出
Before entering name==main Condition satisfied. Before entering name==main No condition satisfied. __mp_main__ Before entering name==main No condition satisfied. __mp_main__ Before entering name==main No condition satisfied. __mp_main__ Before entering name==main No condition satisfied. __mp_main__ Before entering name==main No condition satisfied. __mp_main__ Before entering name==main No condition satisfied. __mp_main__ Before entering name==main No condition satisfied. __mp_main__ Input x 3 and y 4 result 7 Input x 4 and y 5 result 9 Input x 5 and y 6 result 11 Input x 2 and y 3 result 5 Input x 6 and y 7 result 13 Input x 7 and y 8 result 15 Input x 8 and y 9 result 17 Input x 9 and y 10 result 19 result of do add on [9, 8, 7, 6, 5, 4, 3, 2] and [10, 9, 8, 7, 6, 5, 4, 3] : 96 validate 96
用户疑问
- 首次已满足
__name__=="__main__"条件,为何“Before entering name==main”会重复打印? - 为何“No condition satisfied. mp_main”会多次打印?
- 问题出在哪里?
问题解答
1. 重复打印“Before entering name==main”的原因
Python多进程在Windows(或使用spawn启动方式的系统)中,子进程会重新导入主模块(即你运行的测试文件)来复制父进程环境。每次子进程启动时,都会执行测试文件中if __name__=="__main__"之外的顶级代码——包括那行print('Before entering name==main'),所以这行代码会被主进程和每个子进程各执行一次,导致重复打印。
2. 多次打印“No condition satisfied. mp_main”的原因
子进程导入主模块时,__name__的值不是"__main__",而是"__mp_main__"(多进程模块给子进程设置的模块名),所以会进入else分支打印对应内容。你创建了7个进程(cpu_count=7),因此会打印7次该信息。
3. 问题根源与解决方法
问题出在主模块的顶级代码没有被if __name__=="__main__"完全包裹。多进程环境下,主模块中所有不在这个判断块内的代码,都会被每个子进程执行一遍。
解决方法:把测试文件中所有仅需主进程执行的代码(包括那个print)都放到if __name__=="__main__"块内,修改后的测试文件如下:
if __name__=="__main__": print('Before entering name==main') from library.poc.name_main.name_main_2 import do_operate1 print('Condition satisfied.') x = [9,8,7,6,5,4,3,2] y = [10,9,8,7,6,5,4,3] result = do_operate1(x,y) print('result of do add on',x,'and',y,':',result, 'validate', sum(x) + sum(y)) else: print('No condition satisfied.',__name__)
修改后,子进程导入主模块时只会执行else分支(若不需要可直接删除该分支),不会再重复打印主进程的初始化信息。
另外补充:do_operate文件还缺少import multiprocessing和from do_add import do_add的导入语句,实际运行时需要补上,否则会报错。
内容的提问来源于stack exchange,提问作者Prem Ji
相关产品推荐
相关产品推荐

