使用multiprocessing Pool调用其他模块函数时子进程为何不继承全局上下文?
为什么fork子进程中调用其他模块的函数时,globals()不包含主模块的全局变量?
问题核心
你通过fork模式启动子进程,预期子进程继承testfile.py的全局变量a,但在testfile2.py定义的nested_func中调用globals()时,始终找不到a,返回False。
原因分析
函数的globals()返回的是该函数定义所在模块的全局命名空间,和函数被调用的位置完全无关:
nested_func定义在testfile2.py中,所以它的globals()指向的是testfile2模块的命名空间,而非调用它的testfile模块。- fork确实会复制主进程的整个内存空间,包括
testfile.py的全局变量a,但这并不改变nested_func绑定的全局命名空间归属。你可以在主进程中打印nested_func.__globals__ is globals(),结果会是False,直接证明这一点。
解决方案
方案1:将全局变量作为参数传递(推荐,无耦合)
修改nested_func接收额外参数,调用时传入a:
- 修改
testfile.py中的p.map调用:p.map(lambda x: nested_func(x, a), [1, 2]) - 修改
testfile2.py的nested_func:def nested_func(arg, a_val): print(f'''process {os.getpid()} with parent {os.getppid()} has a: {a_val is not None}''')
方案2:将变量注入到目标模块的命名空间
在testfile.py中导入testfile2后,直接把a注入到testfile2的模块命名空间:
from testfile2 import nested_func import testfile2 testfile2.a = a # 将testfile的a注入到testfile2的全局命名空间
这样nested_func调用globals()时就能找到a,输出True。fork子进程会复制主进程的内存状态,所以子进程的testfile2模块也会保留这个a变量。
方案3:在函数内部导入主模块(避免循环导入)
如果允许模块间依赖,可在nested_func内部导入testfile模块来访问变量:
def nested_func(*args): import testfile # 放在函数内部避免循环导入 print(f'''process {os.getpid()} with parent {os.getppid()} inside nestedfunc has global a in testfile: {'a' in testfile.__dict__}''')
内容的提问来源于stack exchange,提问作者Levan Kutsiya
相关产品推荐
相关产品推荐

