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 -~----------~----~----~----~------~----~------~--~---
