jsj*_*jsj 9 python pygtk class
我有一个奇怪的python问题.在我的gtk python应用程序的执行过程中,我的一些类对象神秘地丢失属性,导致程序的某些功能中断.
很难理解为什么会发生这种情况 - 我从不故意删除属性,并且有问题的类继承自我自己编写的类(而不是其他类).
我可以通过重复执行某个操作来触发问题(例如,生成对add_card
方法的多次调用- 通过疯狂点击或打开文件,导致add_card
被调用20次左右)
我真的很茫然,我希望我能提供更多有用的信息给你.
什么可能导致python对象丢失属性?
编辑,回复.问题:
以下是与"失去的两个属性"相关的示例回溯:
Traceback (most recent call last):
File "lib/genericlist.py", line 90, in cursor_changed
if self.viewer:
AttributeError: 'DeckerRunnerList' object has no attribute 'viewer'
Traceback (most recent call last):
File "lib/genericlist.py", line 100, in row_activated
selection = self.TABLE_NAME+"&&"+text
AttributeError: 'DeckerRunnerList' object has no attribute 'TABLE_NAME'
Run Code Online (Sandbox Code Playgroud)
这是他们设置的地方:
class DeckerGenericList(object):
def __init__(self, database, viewer=None, deck=None):
super(DeckerGenericList, self).__init__()
self.database = database
self.viewer = viewer
self.deck = deck
#TABLE_NAME is set in the subclass constructor
Run Code Online (Sandbox Code Playgroud)
这个特殊的子类不会调用它的超类,__init__
因此属性集在子类中重复:
class DeckerRunnerList(DeckerGenericList):
def __init__(self, database, viewer=None, deck=None):
self.database = database
self.viewer = viewer
self.deck = deck
self.TABLE_NAME = "runners"
Run Code Online (Sandbox Code Playgroud)
DeckerGenericList的所有其他子类都有相同的问题,它们都是这样定义的:
class DeckerGearList(DeckerGenericList):
def __init__(self, database, viewer=None, deck=None):
self.TABLE_NAME = "gear"
#... some other class attributes
super(DeckerGearList, self).__init__(database, viewer=viewer, deck=deck)
Run Code Online (Sandbox Code Playgroud)
那么您可以使用属性和检查模块来跟踪属性的更改,如下所示:
import sys
import inspect
def from_where_called():
info = inspect.getframeinfo(sys._getframe(2))
code = info.code_context[0] if info.code_context else ''
return '%s:%s %s' % (info.filename, info.lineno, code)
def add_watched_attribute(name):
def attr_watch_get(self):
value = getattr(self, '_' + name, 'unset')
print from_where_called(), name, 'is', value
return value
def attr_watch_set(self, value):
print from_where_called(), name, 'set to', value
setattr(self, '_' + name, value)
def attr_watch_delete(self):
print from_where_called(), name, 'deleted'
delattr(self,'_' + name)
sys._getframe(1).f_locals[name] = property(
attr_watch_get, attr_watch_set, attr_watch_delete
)
class InspectedClass(object):
add_watched_attribute('victim')
def __init__(self):
self.victim = 2
def kill(self):
del self.victim
x = InspectedClass()
x.victim = 'asdf'
x.kill()
Run Code Online (Sandbox Code Playgroud)
或者您可以使用此答案中的 sys.settrace:/sf/answers/938340651/