如何让多进程启动的函数使用导入的模块别名myfile?
解决多进程中模块别名未定义的问题
问题原因
用multiprocessing启动子进程时,每个子进程都会重新加载main.py模块,但子进程不会执行if __name__ == "__main__"代码块里的内容——这是Python多进程防止无限递归启动的机制。你之前把myfile的导入逻辑放在这个代码块里,导致子进程里根本没定义myfile变量,自然会报NameError。
方案一:将模块导入移到全局作用域(推荐)
把根据config导入模块的代码放到if __name__ == "__main__"外面,这样子进程加载main.py时也能执行导入,拿到myfile变量。
示例代码:
# main.py import sys # 根据配置导入目标模块,放在全局作用域 config = sys.argv[1] # 这里假设从命令行获取配置,也可以从配置文件读取 if config == "generic": import generic as myfile elif config == "no_choice": import no_choice as myfile else: raise ValueError("无效的配置值") def fun1(): myfile.myFunc() def fun2(): myfile.myOtherFunc() if __name__ == "__main__": from multiprocessing import Process p1 = Process(target=fun1) p2 = Process(target=fun2) p1.start() p2.start() p1.join() p2.join()
方案二:给函数传递myfile作为参数
如果不想把导入逻辑放在全局,可以在主进程的if __name__ == "__main__"块里导入myfile,然后把它作为参数传给子进程的函数。模块对象支持序列化(pickle),所以这个方法可行。
示例代码:
# main.py def fun1(myfile): myfile.myFunc() def fun2(myfile): myfile.myOtherFunc() if __name__ == "__main__": from multiprocessing import Process import sys config = sys.argv[1] if config == "generic": import generic as myfile elif config == "no_choice": import no_choice as myfile else: raise ValueError("无效的配置值") # 把myfile作为参数传给子进程函数 p1 = Process(target=fun1, args=(myfile,)) p2 = Process(target=fun2, args=(myfile,)) p1.start() p2.start() p1.join() p2.join()
方案三:用全局变量初始化
如果需要延迟导入,可以先声明一个全局的myfile变量,在主进程里导入后再赋值给它,子进程执行函数时就能拿到这个全局变量。
示例代码:
# main.py myfile = None # 先声明全局变量占位 def fun1(): global myfile myfile.myFunc() def fun2(): global myfile myfile.myOtherFunc() if __name__ == "__main__": from multiprocessing import Process import sys config = sys.argv[1] if config == "generic": import generic myfile = generic elif config == "no_choice": import no_choice myfile = no_choice else: raise ValueError("无效的配置值") p1 = Process(target=fun1) p2 = Process(target=fun2) p1.start() p2.start() p1.join() p2.join()
内容的提问来源于stack exchange,提问作者sighclone
相关产品推荐
相关产品推荐

