Debugging Python:注册现有代码的挂钩,以便在调用函数时获得控制权

Debugging Python:注册现有代码的挂钩,以便在调用函数时获得控制权,debugging,logging,inspection,Debugging,Logging,Inspection,我希望在Python中调用函数时获得控制权(以执行一些先发制人的任务),而不修改源程序,例如调用test()时 def测试(i:int,s:str)->int: 通过 我希望调用一个函数myobserver,并且有一些方法来检查(甚至修改)参数?把它想象成一个小型调试器,例如,将日志添加到不能/不应该修改的现有程序中 def myobserver(句柄) 名称=获取名称(句柄) 对于n,枚举中的arg(获取arg迭代器(句柄)): print(“函数{name}:{arg}的参数{n}”)

我希望在Python中调用函数时获得控制权(以执行一些先发制人的任务),而不修改源程序,例如调用test()时

def测试(i:int,s:str)->int:
通过
我希望调用一个函数myobserver,并且有一些方法来检查(甚至修改)参数?把它想象成一个小型调试器,例如,将日志添加到不能/不应该修改的现有程序中

def myobserver(句柄)
名称=获取名称(句柄)
对于n,枚举中的arg(获取arg迭代器(句柄)):
print(“函数{name}:{arg}的参数{n}”)
ETA:我不是在寻找传统的
装饰器,因为添加装饰器需要更改源代码。(从这个意义上讲,decorator比添加打印更好,但仍然相似,因为它们需要更改源代码。)

您正在寻找python decorator:

从functools导入包装
def调试器(func):
@包装(func)
带有_日志的def(*args,**kwargs):
print(“'+func.'\u name'({},{})”)。格式(*args,**kwargs)+“已调用”)
# -------------------
#你的逻辑在这里
# -------------------
返回函数(*args,**kwargs)
返回并记录日志
@调试器
def测试(i:int,s:str)->int:
打印('我们正在测试',i,s)
测试(10,‘你好’)

编辑

由于上面提到的decorator方法会干扰源代码(必须应用
@
decorator),因此我提出以下建议:

#这是要观察的源代码,不应该碰!!
类源代码:
定义初始化(自我,标签):
self.label=标签
def测试1(自身、i、s):
print('对于标记为{}的对象,我们使用{}和参数{},{}'。格式(self.label,'test1',i,s))
def测试2(自身,k):
print('对于标记为{}的对象,我们使用带有参数{}的{}格式(self.label,'test2',k))
我建议在编写钩子时进行一些手动操作,我不确定这是否可行(我刚刚想到,因此添加):

从functools导入包装
#以下内容基本上是语法和通用的
def挂钩(存在函数、调试器):
@包装(存在函数)
def运行(*args,**kwargs):
返回调试器(exist_func、*args、**kwargs)
回程
#这是你的调试器
def myobserver(源函数,*args,**kwargs):
# -----------------------
#你的逻辑是这样的
# -----------------------
打印('在我的调试器内')
返回原始函数(*args,**kwargs)
# ---------------------------------
obj=源代码(“测试”)
#使包装器准备好接收
no_iterference_hook1=hook(obj.test1,myobserver)
no_iterference_hook2=hook(obj.test2,myobserver)
#根据您选择的函数调用调试器
无参考1(10,‘你好’)
无参考2(“另一个”)

Decorators是重写函数的一种(通常是好的)方法,但decorator违反了“将日志添加到不能/不应该修改的现有程序中”的要求。@MikeG完成了编辑(建议的)任务解决方案对您的情况有帮助吗?我认为使用第二种解决方案可能会使您不再需要手动注册挂钩并调用它们;如果我能弄明白,我会更新的!钩子并不能解决我的问题,我正在寻找一些没有代码mods的东西(如果没有钩子,我想唯一的另一个选择是将watcher添加到python解释器本身!如果有意义,请看一看。或者使用