如何跨模块终止已启动的multiprocessing多进程?
问题根因
原有方案失效的核心原因是
multiprocessing创建子进程时会生成独立的内存地址空间,父进程(模块B调用的A模块主进程)修改的全局keep_running和子进程内运行的keep_running是完全独立的两个变量,变更无法同步,自然控制不了子进程的循环。
最佳实现方案
这个场景最适合用multiprocessing.Event作为跨进程停止信号,它是官方提供的进程安全同步原语,无需全局变量,同时支持子进程优雅退出,避免强制杀进程带来的业务数据异常、资源未释放等问题。
修改后模块A代码
import multiprocessing import time # 全局配置对象按你原有逻辑保留即可 configs = None def start_it(arg, stop_event): # 用事件状态替代全局变量控制循环 while not stop_event.is_set(): # 替换为你实际的业务逻辑 do_stuff(arg) time.sleep(1) def main(args): global configs # 原有配置初始化逻辑保留 configs = configs.configurations.Configurations() # 初始化停止信号事件 configs.stop_event = multiprocessing.Event() # 把事件作为参数传给子进程 configs.process = multiprocessing.Process(target=start_it, args=(arg, configs.stop_event)) configs.process.start() def stop_it(conf): # 触发停止信号,通知子进程退出循环 configs.stop_event.set() # 等待子进程优雅退出,避免产生僵尸进程 configs.process.join(timeout=3) # 超时未退出则强制终止作为兜底 if configs.process.is_alive(): configs.process.terminate() if __name__ == '__main__': import sys main(sys.argv[1:])
修改后模块B代码
仅需修正原有导入错误即可,业务逻辑无需调整:
import A as m def on_init(<args>): m.main([conf_file, database]) def on_stop(conf): m.stop_it(conf)
注意事项
- 该方案跨平台兼容,不管是Unix的fork模式还是Windows的spawn模式都可以正常工作
- 如果你的
do_stuff逻辑执行耗时较长,可以在其内部也插入stop_event.is_set()的判断,收到停止信号后可以提前退出当前任务 - stop_it中
join的超时时间可以根据你的业务单次执行时长灵活调整,避免正常还没执行完的逻辑被误杀
内容的提问来源于stack exchange,提问作者Guy
相关产品推荐
相关产品推荐

