循环导入及async/await场景下全局变量未定义报错问题咨询
问题排查与解决
1. NameError报错根因
这个错误和多进程、async/await均无关,是循环导入+全局变量初始化时机错误导致的:
- 运行
main模块时,首先会执行顶层的import api语句 api模块执行时又会导入main,此时main模块的main()函数还未运行,全局变量lock尚未定义- 后续调用
main.log()时,函数内部引用未初始化的lock,直接触发NameError
另外可以明确:async/await是单线程协程模型,本身不会创建任何新进程,你观察到的非主进程PID,是后续multiprocessing相关逻辑触发的子进程导入导致的,和协程无关。
2. 修复方案
第一步:解除循环导入
不要让main和api互相依赖,将公共的日志函数、全局锁抽离到独立的公共模块,例如新建common.py:
import multiprocessing # 直接在模块顶层初始化锁,导入时即可完成创建 lock = multiprocessing.Lock() def log(msg): print(multiprocessing.current_process().pid) with lock: some_log_func(msg)
之后main和api都导入common.log使用即可,不需要互相导入。
第二步:子进程共享锁的处理
根据你使用的多进程启动模式,对应处理锁的继承:
- fork模式(Linux/macOS默认):父进程初始化的锁会自动被子进程继承,只要锁是在创建子进程前初始化完成,即可直接在子进程中使用。
- spawn模式(Windows默认):创建子进程时会重新导入所有模块,不会自动继承父进程的全局变量,需要通过进程池的初始化函数传递锁:
# main模块代码示例 import multiprocessing from common import lock def pool_init(shared_lock): # 给子进程的全局变量赋值 import common common.lock = shared_lock if __name__ == '__main__': pool = multiprocessing.Pool( processes=4, initializer=pool_init, initargs=(lock,) ) # 后续使用进程池执行任务即可
内容的提问来源于stack exchange,提问作者awarrier99
相关产品推荐
相关产品推荐

