Обновление 2013-02-08
Теперь у меня есть идея, почему я не смог воспроизвести эту проблему в небольшом фрагменте тестового кода. В небольшой программе сборщик мусора в Python не очень активен. Я считаю, что проблема в том, что Python собирает некоторые объекты, на которые есть ссылки только в GObject. Я думаю, что это регрессия с участием этой ошибки или новой аналогичной ошибки.
Я понял это, потому что снова столкнулся с той же проблемой, но с моим собственным классом (который имеет ссылки только из объектов GObject) - на этот раз весь dict стирается на объекте. Если я использую код здесь , чтобы отслеживать один из атрибутов, который исчезает, он не исчезает! Кажется, дополнительная ссылка хранит атрибуты. Это пахнет проблемой сборщика мусора. Я подтвердил это, добавив объект в глобальный список во время инициализации ... это также устраняет проблему, как это происходит сейчас.
Оригинальная проблема
У меня странное поведение с графическим интерфейсом PyGTK. У меня есть объект, который постоянно теряет большое количество атрибутов. Я пытаюсь определить, является ли это ошибкой в моем коде, интерпретаторе Python или PyGTK.
Я не звоню на delattr()
. Я попытался определить, вызывает ли что-нибудь метод __delattr__()
моего объекта, переопределив __delattr__()
кодом, который всегда вызывает исключение. Я могу воспроизвести событие, которое приводит к тому, что объект теряет свои атрибуты, но исключение никогда не возникает. Я не уверен в другом способе выяснить, какие вызовы функций (если таковые имеются) вызывают потерю атрибутов объекта.
Рассматриваемый объект работает идеально все время, пока он внезапно не потеряет атрибуты, к которым я пытаюсь получить доступ.
Потеря атрибута происходит последовательно после выполнения некоторых действий в графическом интерфейсе, которые не имеют ничего общего с объектом, который теряет атрибуты. Я обнаружил это случайно; могут быть другие действия, которые приводят к тому, что объект теряет свои атрибуты.
Я добавил print id(self)
к методу, который обращается к исчезающему атрибуту. Идентифицируемый идентификатор до и после исчезновения атрибута.
Любые предложения о том, как отследить источник этой проблемы?
Ссылочный код ниже: (Примечание. Я обновлю этот код, если / когда придумаю упрощенный тестовый пример, который воспроизводит проблему. Прямо сейчас весь код, необходимый для воспроизведения ошибки слишком велик для размещения здесь.)
Вот класс для моего объекта, который теряет свои атрибуты. Это, очевидно, минимизированная версия реального функционального кода, но я использую это для отладки, и проблема все еще возникает.
Это подкласс моего пользовательского 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
, и он тоже исчезает.