能否在Python中利用 MPxNode 的构造和析构函数来添加和删除事件?

最近有看到一个case,用户用Python自定义了一个节点,然后在自定义节点的构造函数 __init__ 中注册了一个事件回调函数,并且在相应的析构函数__del__ 中把对应的事件删除掉。代码看起来似乎没有什么问题,但是当用户执行的时候,发现该事件总是无法被删除掉。无论是重新建一个场景,或者是删除这个节点,甚至是卸载这个插件,该事件一直存在,没有被删除掉。 

import sys

import maya.OpenMaya as OpenMaya

import maya.OpenMayaMPx as OpenMayaMPx

nodeName = "TestNode"

nodeId = OpenMaya.MTypeId(0x102fff)

class Test(OpenMayaMPx.MPxNode):

    idCallback = None

        

    def __init__(self):

        OpenMayaMPx.MPxNode.__init__(self)   

        if self.idCallback==None :

            self.idCallback = OpenMaya.MEventMessage.addEventCallback("SelectionChanged",self.callbackFunc)       

    def __del__(self):

        try:

            OpenMaya.MEventMessage.removeCallback(self.idCallback)

        except:

            print str(self.idCallback) + "already destroyed."

   

    def callbackFunc(self,*args):

        print "Called"

    def compute(self, plug, dataBlock):

        print "compute"

def nodeCreator():

    nodePtr = OpenMayaMPx.asMPxPtr(Test())

    return nodePtr

def nodeInitializer():

    print "nodeInitializer"

   

def initializePlugin(mobject):

    mplugin = OpenMayaMPx.MFnPlugin(mobject)

    try:

        mplugin.registerNode(nodeName, nodeId, nodeCreator, nodeInitializer)       

    except:

        sys.stderr.write("Failed to register node: %s" % nodeName)

        raise

def uninitializePlugin(mobject):

    mplugin = OpenMayaMPx.MFnPlugin(mobject)

    try:

        mplugin.deregisterNode(nodeId)

    except:

        sys.stderr.write("Failed to deregister node: %s" % nodeName)

        raise

仔细看了下问题并且在Maya环境中运行了下,发现问题在于析构函数__del__中,该函数在上述几种情况下一直无法被调用到。查了下Python析构函数的特性,这才发现了问题原因所在。 

因为Python是用了自动垃圾回收(GC)来管理其内存的,也就是说,对象的真正析构时机是由GC来控制的。那么,当我们新建场景,删除节点,或者是卸载插件的时候,虽然表面上看该节点已经被删除了,但是其实际上很有可能还没有被GC回收,所以该析构函数也就一直没有被调用到。 

如果想要让对象被删除掉,可以直接显式调用删除语句 del,这样才能强制GC去删除该对象。

原文地址:https://www.cnblogs.com/johnonsoftware/p/2933178.html