Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/345.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/design-patterns/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python类丢失属性_Python_Class_Pygtk - Fatal编程技术网

Python类丢失属性

Python类丢失属性,python,class,pygtk,Python,Class,Pygtk,我有一个特殊的python问题。在执行gtk python应用程序的过程中,我的一些类对象神秘地丢失了属性,导致程序的一些功能中断 很难理解为什么会发生这种情况——我从来没有故意删除属性,并且所讨论的类继承自我自己编写的类(没有其他类) 我可以通过重复执行某个操作来触发问题(例如,生成对add\u card方法的多次调用-通过疯狂单击或打开文件,导致add\u card被调用二十次左右) 我真的不知所措,我希望我有更多我认为有用的信息给你 什么会导致python对象丢失属性 编辑,重新编辑。问题

我有一个特殊的python问题。在执行gtk python应用程序的过程中,我的一些类对象神秘地丢失了属性,导致程序的一些功能中断

很难理解为什么会发生这种情况——我从来没有故意删除属性,并且所讨论的类继承自我自己编写的类(没有其他类)

我可以通过重复执行某个操作来触发问题(例如,生成对
add\u card
方法的多次调用-通过疯狂单击或打开文件,导致
add\u card
被调用二十次左右)

我真的不知所措,我希望我有更多我认为有用的信息给你

什么会导致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'
下面是它们的设置位置:

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
这个特定的子类不调用它的超类
\uuuu init\uuuu
,因此属性集在子类中是重复的:

class DeckerRunnerList(DeckerGenericList):

      def __init__(self, database, viewer=None, deck=None):

        self.database = database
        self.viewer = viewer
        self.deck = deck
        self.TABLE_NAME = "runners"
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)
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()

您可以使用property和inspect模块跟踪对属性的更改,如下所示:

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)
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()
或者您可以使用sys.settrace来回答这个问题:

PyQT(因此也可能是PyGtk或其他框架)有一种奇怪的行为,即实际上在属性代码中/下面的某个位置引发AttributeError会使python报告该对象上被调用的属性不存在

关于这是为什么(实际上是正确的和可以理解的行为),有一个(更官方的)故事。它与在基类上定义uu getattr_uu有关:其工作原理是,如果对对象调用属性导致AttributeError,则调用u getattr_u方法。但该方法不知道实际找不到什么“属性”。由于(PyQt.QObject)u_getattr_u_______________________________________

无论如何,可能是您从某个使用_ugetattr_uuu的对象继承,并且您自己的属性代码确实调用了(另一个)属性,而该属性确实不存在。要检查这一点,您可以执行以下操作:

@property
def myproperty:
   try:
      doStuff..
   except AttributeError as e:
      print "Got ya! It is withing the attribute:", repr(e)
      raise ValueError("Got an AttributeError within my attribute!")

更新/注意:另外,如果您自己在DeckerGenericList对象上实现uu getattr,出于同样的原因,请小心使用它!提高AttributeError在u_getattr_u__________________________________。请注意,没有简单的修复方法:“真正的”AttributeError只携带一个字符串消息(而不是具体的实际属性名称),但更重要的是:“\uu getattr\uuuu”函数从一开始就不会看到原始的AttributeError。

我认为这是一个垃圾收集器错误。我有一个类似的问题,我想我已经把它缩小到GC

尝试在包含丢失属性的类的模块顶部添加一个列表
extra_references=[]
。在类的
\uuuu init\uuuu
方法中,添加以下代码:

global extra_references
extra_references.append(self)
这将确保始终存在对GObject之外的对象的引用


如果问题消失了,那么Python的垃圾收集器会在您处理完对象之前吃掉它。闻起来很像这个bug(据说已经修复):

你在使用线程吗?你能展示一些代码吗?DeckerRunneList的定义在哪里?FWIW,
self。TABLE_NAME
可能是一个类属性,而不是实例属性,显示实际使用类并引发该错误的示例代码。可能是显示该行为的最小示例。没有这个,我们怎么知道你在干什么?看起来可能是某种明显的pygtk味道。。。检查一下:我只是在尝试进一步调查时使用了这段代码,它非常有用。谢谢