Python对其他模块类执行Monkey Patch时的NameError问题排查
解决猴子补丁中
log未定义的问题 问题出在你定义的new_bork函数作用域里没有log这个名称——原模块的define_bork能调用log,是因为dog_module.py里已经从._util导入了log,但你的补丁函数是在自己的脚本里定义的,不在原模块的作用域内,自然找不到log。
有两种简单的解决方式:
方法1:从dog_module导入log
既然dog_module已经导入了_util里的log,直接在你的脚本里引入这个log即可:
import dog_module # 从dog_module导入它已经加载好的log from dog_module import log def new_bork(self, bark, breed): result = bark log.info('Importing: %r', bark) if breed == "big": result = bark + "!" return result class Dog: def __init__(self, color, breed): self.color = color self.breed = breed # 先打补丁再生成结果,避免递归调用问题 dog_module.Bork.define_bork = new_bork bark = dog_module.Bork() self.woof = bark.define_bork("woof", self.breed) my_dog_spot = Dog("black", "big")
方法2:直接使用dog_module.log
不需要额外导入,在补丁函数里直接通过原模块访问log:
import dog_module def new_bork(self, bark, breed): result = bark # 直接用dog_module里的log对象 dog_module.log.info('Importing: %r', bark) if breed == "big": result = bark + "!" return result class Dog: def __init__(self, color, breed): self.color = color self.breed = breed # 先打补丁再生成结果,避免递归调用问题 dog_module.Bork.define_bork = new_bork bark = dog_module.Bork() self.woof = bark.define_bork("woof", self.breed) my_dog_spot = Dog("black", "big")
另外注意:原代码中__init__里调用self.woof()会触发递归调用(因为woof是实例方法,调用它会再次执行方法体),上面的代码已经修正了这个问题——把补丁逻辑和结果生成直接放在__init__里,避免不必要的递归,同时补丁只需要执行一次即可。
内容的提问来源于stack exchange,提问作者mrkanuke
相关产品推荐
相关产品推荐

