我如何找出为什么/何时Python对象丢失属性?
作者:互联网
更新2013-02-08
现在我有了一个主意,为什么我无法在一小段测试代码中重现此问题.在一个小程序中,Python的垃圾收集器不是很活跃.我相信问题在于Python正在收集一些仅在GObject中引用的对象.我认为这是涉及this bug的回归,或者是一个新的类似错误.
我想出了这个原因,因为我再次遇到了相同的问题,但是使用了自己的类(该类仅具有来自GObject对象的引用),这一次整个dict都在该对象上消失了.如果我使用代码here监视消失的属性之一,它不会消失!似乎额外的引用使属性保持不变.那闻起来像垃圾收集器的问题.我通过在初始化期间将对象添加到全局列表中来确认了这一点……这也解决了现在出现的问题.
原始问题
我在使用PyGTK GUI时遇到一些奇怪的行为.我有一个始终丢失大量属性的对象.我试图确定这是否是我的代码,Python解释器或PyGTK中的错误.
我没有调用delattr().我试图通过用总是引发异常的代码覆盖__delattr __()来检测是否有任何东西正在调用对象的__delattr __()方法.我能够重现导致对象丢失其属性的事件,但从未引发异常.我不确定另一种方法来找出导致对象丢失属性的函数调用(如果有).
有问题的对象一直可以完美工作,直到它突然失去我尝试访问的属性.
在GUI中执行某些与丢失属性的对象无关的操作后,属性丢失会持续发生.我是偶然发现的.可能还有其他动作导致对象失去其属性.
我已经将print id(self)添加到访问消失属性的方法中.属性消失之前和之后打印的ID相同.
关于如何找到此问题根源的任何建议?
下面的参考代码:(注意:如果/当我提出一个重现问题的简化测试用例时,我将更新此代码.现在,重现该错误所需的总代码太大,无法在此处发布.)
这是丢失其属性的对象的类.显然,这是实际功能代码的最小化版本,但是我正在使用它进行调试,但问题仍然存在.
它是我的自定义MenuBar类的子类.
请注意,on_file_import__activate()方法通过父类之一连接到菜单项的信号.
class FluidClassManagerWindowMenu(MenuBar):
menu_items = [("File",("Import",))]
def __init__(self, parent):
# XXX: different name than self.parent to see if it stops disappearing
self._xxx_my_parent = parent
MenuBar.__init__(self, parent)
def __delattr__(self,attr):
# XXX: trying to find the cause for lost attributes
traceback.print_stack()
def on_file_import__activate(self, widget=None, data=None):
# XXX: this is the same before and after the attributes disappear
print id(self)
# XXX: print the list of attributes to see what disappears
print dir(self)
# XXX: this works until the _xxx_my_parent attribute disappears
print self._xxx_my_parent
如果您感到好奇,这是我的MenuBar类的完整资源.它是pygtkhelpers SlaveView,它继承自GObject. pygtkhelpers委托将自动魔术信号连接到上面的on_file_import__activate方法.
class MenuBar(pygtkhelpers.delegates.SlaveView):
def __init__(self, parent):
SlaveView.__init__(self)
self.parent = parent
def create_ui(self):
menu_bar = gtk.MenuBar()
menu_bar.set_pack_direction(gtk.PACK_DIRECTION_LTR)
for menu_name, items in self.menu_items:
menu = gtk.Menu()
submenu = gtk.MenuItem(menu_name)
submenu.set_submenu(menu)
for item_name in items:
if not item_name:
menu.append(gtk.MenuItem())
continue
menuitem = gtk.MenuItem(item_name)
fixed_item_name = item_name.lower().replace(' ','_')
fixed_menu_name = menu_name.lower().replace(' ','_')
attr_name = '%s_%s' % (fixed_menu_name,fixed_item_name)
# set an attribute like self.edit_vial_layout
# so pygtkhelpers can find the widget to connect the signal from
setattr(self,attr_name,menuitem)
menu.append(menuitem)
menu_bar.append(submenu)
self.vbox = gtk.VBox()
self.vbox.pack_start(menu_bar)
self.vbox.show_all()
self.widget.add(self.vbox)
从对象中消失的属性列表:
‘_model’,’_ props’,’_ toplevel’,’_ xxx_my_parent’,’file_import’,’parent’,’slaves’,’testtesttest’,’vbox’,’widget’
属性parent是最初消失的东西;我尝试将其值分配给_xxx_my_parent
ManagerWindowMenu .__ init __(),但它也会消失.我还在MenuBar .__ init__中添加了一个我从未访问过的新属性,称为testtesttest,它也消失了.
解决方法:
请记住,PyGTK中的对象通常继承自GObject. GObject框架中可能发生活动,导致您丢失属性.
标签:pygtk,python 来源: https://codeday.me/bug/20191102/1994273.html