开发者

python thread exception errors when exit the whole program

HI, guys,

I am developing a GUI with python 2.4.3 and wxpython. Everything works fine except when I exit main program(close the main window of GUI). The wierd thing is that sometimes there is such error, sometimes there is no error at all. Although I found the same error reports from the python mailing list(the link is http://bugs.python.org/issue1722344, I am not sure if my case is the same as this one). I do not know how it is finally solved and what I should do to overcome this problem.

The error message from the console is as follows.

Exception in thread Thread-1 (most likely raised during interpreter shutdown):
Traceback (most recent call last):
  File "/usr/lib/python2.4/threading.py", line 442, in __bootstrap
  File "/opt/company/workspace/username/application/src/mainwidget.py", line 1066, in run
  File "/usr/lib/python2.4/Queue.py", line 89, in put
  File "/usr/lib/python2.4/threading.py", line 237, in notify
exceptions.TypeError: exceptions must be classes, instances, or strings (deprecated), not NoneType
Unhandled exception in thread started by 
Error in sys.excepthook:

Original exception was:

The following is part of my code(the thread related code is complete, I extract the main operations for the rest). when I use the GUI to launch an external subprocess, at the same time, a wx.TextCtrl object is created. This wx.TextCtrl object is used to give input and print output of the external subprocess

class BashProcessThread(threading.Thread):
    def __init__(self, readlineFunc):
        threading.Thread.__init__(self)
        self.readlineFunc = readlineFunc
        self.lines = []
        self.outputQueue = Queue.Queue()
        self.setDaemon(True)

    def run(self):
        while True:
           line = self.readlineFunc()
           self.outputQueue.put(line)
           if (line==""):
            break
        return ''.join(self.lines)

    def getOutput(self):
        """ called from other thread """            
        while True:
            try:
                line = self.outputQueue.get_nowait()
                lines.append(line)
            except Queue.Empty:
                break
        return ''.join(self.lines)

class ExternalProcWindow(wx.Window):
    def __init__(self, parent, externapp):
        wx.Window.__init__(self, parent, -1, pos=wx.DefaultPosition, size = wx.Size(1200, 120))
        self.externapp=externapp
        self.prompt = externapp.name.lower() + '>>'
        self.textctrl = wx.TextCtrl(self, -1, '', size= wx.Size(1200, 120), style=wx.TE_PROCESS_ENTER|wx.TE_MULTILINE)
        self.default_txt = self.tex开发者_高级运维tctrl.GetDefaultStyle()
        self.textctrl.AppendText(self.prompt)
        self.outputThread = BashProcessThread(self.externapp.sub_process.stdout.readline)
        self.outputThread.start()
        self.textctrl.SetFocus()
        self.__bind_events()         
        self.Fit()

    def __bind_events(self):
        self.Bind(wx.EVT_TEXT_ENTER, self.__enter)

    def __enter(self, e):
        nl=self.textctrl.GetNumberOfLines()
        ln =  self.textctrl.GetLineText(nl-1)
        ln = ln[len(self.prompt):]     
        self.externapp.sub_process.stdin.write(ln+"\n")
        time.sleep(.3)
        self.textctrl.AppendText(self.outputThread.getOutput())

class ExternApp:
    def launch(self):
        self.sub_process = subprocess.Popen(launchcmd, stdin=subprocess.PIPE, 
                stdout=subprocess.PIPE, stderr=subprocess.PIPE)


The problem is caused by the use of threading.Thread.setDaemon. Threads set daemonic don't prevent the Python intepreter from exiting, but they still keep running. Because Python cleans up the environment before the process is terminated, the threads can run into trouble when stuff is removed from under them. That raises an exception, which the thread class tries to print for your convenience -- but that, then, too fails because the process is exiting.

You could try to silence the exception, but that's tricky (and if the thread does anything substantial, it might hide a real problem. Not the case here, though.) Or you could ask the thread to stop before exiting, and not set the thread daemonic. Or you can simply avoid using threads altogether. I do not remember if wxPython has a convenient mechanism for getting a process's output or even of doing asynchronous I/O, but many GUI toolkits do. And there's always Twisted, which does it all for you.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜