gpt4 book ai didi

python - 如何在没有 dunder setattr 或 pdb 的情况下观察 python 中的变量变化

转载 作者:太空狗 更新时间:2023-10-29 17:06:41 24 4
gpt4 key购买 nike

有一个大型 python 项目,其中一个类的一个属性在某些地方有错误的值。

它应该是 sqlalchemy.orm.attributes.InstrumentedAttribute,但是当我运行测试时它是常量值,假设是字符串。

有什么方法可以在 Debug模式下运行 python 程序,并在代码行的每一步后自动运行一些检查(如果变量类型改变)?

附言我知道如何在检查和属性装饰器的帮助下记录类实例属性的更改。可能在这里我可以将此方法与元类一起使用...

但有时我需要更通用和更强大的解决方案...

谢谢。

附言我需要类似的东西:https://stackoverflow.com/a/7669165/816449 ,但可能会对该代码中发生的事情进行更多解释。

最佳答案

好吧,这是一种缓慢的方法。可以修改它以监视局部变量的变化(仅按名称)。它是这样工作的:我们执行 sys.settrace 并在每一步分析 obj.attr 的值。棘手的部分是我们在执行行之前收到 'line' 事件(某行已执行)。所以,当我们注意到 obj.attr 发生变化时,我们已经在下一行了,我们无法获取上一行的帧(因为没有为每一行复制帧,它们被修改了)。因此,在每一行事件中,我将 traceback.format_stack 保存到 watcher.prev_st 并且如果在下一次调用 trace_command 时值已更改,我们打印将堆栈跟踪保存到文件。在每一行上保存回溯是一项非常昂贵的操作,因此您必须将 include 关键字设置为项目目录列表(或只是项目的根目录),以免观察其他人如何图书馆正在做他们的事情并浪费 CPU。

watcher.py

import traceback

class Watcher(object):
def __init__(self, obj=None, attr=None, log_file='log.txt', include=[], enabled=False):
"""
Debugger that watches for changes in object attributes
obj - object to be watched
attr - string, name of attribute
log_file - string, where to write output
include - list of strings, debug files only in these directories.
Set it to path of your project otherwise it will take long time
to run on big libraries import and usage.
"""

self.log_file=log_file
with open(self.log_file, 'wb'): pass
self.prev_st = None
self.include = [incl.replace('\\','/') for incl in include]
if obj:
self.value = getattr(obj, attr)
self.obj = obj
self.attr = attr
self.enabled = enabled # Important, must be last line on __init__.

def __call__(self, *args, **kwargs):
kwargs['enabled'] = True
self.__init__(*args, **kwargs)

def check_condition(self):
tmp = getattr(self.obj, self.attr)
result = tmp != self.value
self.value = tmp
return result

def trace_command(self, frame, event, arg):
if event!='line' or not self.enabled:
return self.trace_command
if self.check_condition():
if self.prev_st:
with open(self.log_file, 'ab') as f:
print >>f, "Value of",self.obj,".",self.attr,"changed!"
print >>f,"###### Line:"
print >>f,''.join(self.prev_st)
if self.include:
fname = frame.f_code.co_filename.replace('\\','/')
to_include = False
for incl in self.include:
if fname.startswith(incl):
to_include = True
break
if not to_include:
return self.trace_command
self.prev_st = traceback.format_stack(frame)
return self.trace_command
import sys
watcher = Watcher()
sys.settrace(watcher.trace_command)

testwatcher.py

from watcher import watcher
import numpy as np
import urllib2
class X(object):
def __init__(self, foo):
self.foo = foo

class Y(object):
def __init__(self, x):
self.xoo = x

def boom(self):
self.xoo.foo = "xoo foo!"
def main():
x = X(50)
watcher(x, 'foo', log_file='log.txt', include =['C:/Users/j/PycharmProjects/hello'])
x.foo = 500
x.goo = 300
y = Y(x)
y.boom()
arr = np.arange(0,100,0.1)
arr = arr**2
for i in xrange(3):
print 'a'
x.foo = i

for i in xrange(1):
i = i+1

main()

关于python - 如何在没有 dunder setattr 或 pdb 的情况下观察 python 中的变量变化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13402847/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com