编程语言
首页 > 编程语言> > 我如何找出为什么/何时Python对象丢失属性?

我如何找出为什么/何时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