Have you tried setting Thread.deamon / Thread.setDaemon() ?
If the thread is not daemonic, it may block python finalization.

-Chris

On Wed, Sep 16, 2009 at 6:25 AM, thirstydevil <[email protected]> wrote:
>
> I've noticed a few issues using PyQt and pumpThread.  It seems that
> randomly when users closes Maya it will do 1 of these:
>
> 1) Close successfully.
> 2) Not closes. Instead require 2 close requests by the user.
> 3) Closes but leaves 1 Maya thread running ( the pumpThread ) and
> still consuming Maya's memory footprint
>
> In an attempt to understand the problem I've reconfigured pumpThread
> based on Jon's and another user's version posted here (can't remember
> who and cant be bothered to hunt for it again, sorry to who ever you
> are).  I'll blat out my thoughts and you guys can hopefully correct me
> or confirm my understanding.
>
> -----------------------------------------------------------------------------------------------------------------------------------------------------------------
>
> I've not done any multi threading stuff before, but this is what I
> understand is happening with pumpThread and the way in which it's
> operating.
>
> pumpThread is spawning 1 sub thread from Maya's main thread.  The UI
> is executing in that new thread.
> threading.Thread( target = pumpQt, args = () )
>
> Whenever a maya cmd is called in the PyQt UI code it is called with
> utils.executeDeferred( processor ) in pumpQt block.
>
> This intern is executed in maya's main thread when it can.  I simply
> added the following line to the pumpQt whille loop print "pump..."
> makes sure a maya cmd is called every pumpThread cycle.
>
> As this loop is executing quicker than maya's main loop and stack of
> evalDeffered print statements build up in the main thread.  In my
> pumpThread module I've created a global for the while loop (gPump).
> Using killPumpThread I can instantly stop and close the thread.  But
> Maya is still printing "pump..." untill the stack of evalDeffered cmds
> have finished.
>
> Here's my test code with my new pumpThread module
>
> import pumpThread
> pumpThread.initializePumpThread()
> # Wait 20 secs
> pumpThread.killPumpThread()
> # only a small number of prints executed after thread is closed. Maybe
> 2-5 cycle depending
>
> # Load my PyQt UI and leave open and pumping for 20secs
> pumpThread.killPumpThread()
> # window closes quickly and tread die's in Task Manager.  But 926
> lines of pump... printed  before maya is finished
>
> So how does that relate to the 3 errors above?
>
> 1) Close successfully.
> Thread has closed in time and Maya has no evaldeffers in the stack
>
> 2) Not closes. Instead require 2 close requests by the user.
> Thread has closed in time but maya is still pumping
>
> 3) Closes but leaves 1 Maya thread running ( the pumpThread ) and
> still consuming Maya's memory footprint
> Thread didn't close, UI could have been left open or maya not closing
> sun threads properly?
>
> It seems I can't do anything about error 2  as this is down to how
> much and often the threads are communicating.  But I can help on error
> 3 by calling pumpThread.killPumpThread() with a script job on Maya
> exit.
>
> "RANT ON"
> I've spent nearly 6 months researching PyQt in Maya and so far
> (especially if you are having to support 64bit) I have to say it's
> allot of pain to maintain.  Maya doesn't play nicely and will crash
> with no warning if you try to do something wrong or something it's not
> happy with.  When you have 12 UI modules and 500 - 3000 lines of code
> in each it is a real headache to comment out blocks of code to find
> the line that is crashing Maya.  Sometimes it's not you.  I had one
> example where by I was creating a QIcon as a module global, it was
> being used allot in the UI.  This line had been in for months, but all
> of a sudden was crashing Maya.  I had to put the QIcon inside a class
> to solve the Maya crash.  Developing a complex UI as I have with PyQT
> with lots of dependencies on Maya tools, like Pymel and clr means that
> you loose the ability to run the UI in Wings with debugging.
> Something you really need.  Instead. I think using C++ Qt would give
> you the hooks to run in debug mode with Maya.  You wouldn't have to
> compile 64bit PyQt as well.  But then you loose the benefits of
> developing in a scripting environment.
> "RANT OFF"
>
> I'm sure that other studios trying to implement PyQT into there
> pipeline have faced these issues.  I was wondering if anyone else
> could shed some light of the pit falls and hoops you are jumping
> through.
>
> Anyway here is my edited pumpThread module
>
> -Dave
> ----------------------------------------------------------------------------------------------------------------------------------------------------------
>
> from PyQt4 import QtCore, QtGui
> import maya.utils as utils
> import sys
> import time
> import threading
> import gc
> import maya.cmds as cmds
>
> pumpedThread = None
> app = None
> gPump = True
>
> def get_app():
>        global app
>        return app
>
> def set_app(i_app):
>        global app
>        testAppInstance = QtCore.QCoreApplication.instance()
>        if testAppInstance:
>                app = testAppInstance
>        else:
>                app = i_app
>
> def get_pt():
>        global pumpedThread
>        return pumpedThread
>
> def set_pt(i_pt):
>        global pumpedThread
>        pumpedThread = i_pt
>
> def pumpQt():
>        global app
>        global gPump
>        def processor():
>                app.processEvents()
>        while gPump:
>                time.sleep(0.01)
>                utils.executeDeferred( processor )
>                #print "pump..."
>
> def killProcess():
>        global gPump
>        gPump = False
>
> def killPumpThread():
>        if get_app():
>                get_app().closeAllWindows()
>        if get_pt():
>                killProcess()
>                set_pt(None)
>                set_app(None)
>                gc.collect()
>
>
> class QThreader(QtCore.QThread):
>        '''An attempt to use QThread instead of Threading.  Counld get
> this to pump in the same fasion'''
>        def __init__(self, funcPointer, executeDeferred=True):
>                super(QThreader, self).__init__()
>                self.runThread = True
>                self.funcPointer = funcPointer
>                self.executeDeferred = executeDeferred
>
>        def run(self):
>                time = long(1)
>                while self.runThread:
>                        self.usleep(time)
>                        if self.executeDeferred:
>                                utils.executeDeferred(self.funcPointer())
>                        else:
>                                self.funcPointer()
>
>        def killThread(self):
>                self.runThread=False
>
>        def startThread(self):
>                self.runThread=True
>
>
> def initializePumpThread():
>        global gPump
>        gPump = True
>        if get_pt() == None:
>                set_app(QtGui.QApplication(sys.argv))
>                set_pt(threading.Thread( target = pumpQt, args = () ))
>                get_pt().start()
>
>
> >
>

--~--~---------~--~----~------------~-------~--~----~
http://groups.google.com/group/python_inside_maya
-~----------~----~----~----~------~----~------~--~---

Reply via email to