Strange threading behaviour

Dave Angel d at davea.name
Thu Jun 21 14:28:14 EDT 2012


On 06/21/2012 02:03 PM, Rotwang wrote:
> On 21/06/2012 18:07, Dave Angel wrote:
>> On 06/21/2012 11:19 AM, Rotwang wrote:
>>> Hi all, I'm using Python 2.7.2 on Windows 7 and a module I've written
>>> is acting strangely. I can reproduce the behaviour in question with
>>> the following:
>>>
>>> --- begin bugtest.py ---
>>>
>>> import threading, Tkinter, os, pickle
>>>
>>> class savethread(threading.Thread):
>>>      def __init__(self, value):
>>>          threading.Thread.__init__(self)
>>>          self.value = value
>>>      def run(self):
>>>          print 'Saving:',
>>>          with open(os.path.join(os.getcwd(), 'bugfile'), 'wb') as f:
>>>              pickle.dump(self.value, f)
>>>          print 'saved'
>>>
>>> class myclass(object):
>>>      def gui(self):
>>>          root = Tkinter.Tk()
>>>          root.grid()
>>>          def save(event):
>>>              savethread(self).start()
>>>          root.bind('s', save)
>>>          root.wait_window()
>>>
>>> m = myclass()
>>> m.gui()
>>>
>>> --- end bugtest.py ---
>>>
>>>
>>> Here's the problem: suppose I fire up Python and type
>>>
>>>>>> import bugtest
>>>
>>> and then click on the Tk window that spawns and press 's'. Then
>>> 'Saving:' gets printed, and an empty file named 'bugfile' appears in
>>> my current working directory. But nothing else happens until I close
>>> the Tk window; as soon as I do so the file is written to and 'saved'
>>> gets printed. If I subsequently type
>>>
>>>>>> bugtest.m.gui()
>>>
>>> and then click on the resulting window and press 's', then 'Saving:
>>> saved' gets printed and the file is written to immediately, exactly as
>>> I would expect. Similarly if I remove the call to m.gui from the
>>> module and just call it myself after importing then it all works fine.
>>> But it seems as if calling the gui within the module itself somehow
>>> stops savethread(self).run from finishing its job while the gui is
>>> still alive.
>>>
>>> Can anyone help?
>>>
>>>
>>
>> I did not study your code, as I'm not very familiar with tkinter.
>> However, I think I know your problem:
>>
>> You do not want to try to start up threads from within a import.  An
>> import is special, and somehow blocks threading while it's running.
>
> That would explain it.
>
>
>> Consequently, a module should not try to do anything too fancy from
>> within its top-level code.  Add in the traditional:
>>
>> def main():
>>      m = myclass()
>>      m.gui()
>>
>> if __name__ == "__main__":
>>      main()
>>
>> and just run it from the command line, as    python bugtest.py
>
> In fact, running the module directly from the command line makes it
> work properly as-is.

But if you leave it as-is, then you can't run it from the interactive
interpreter.

>
> Thanks for your post.
>

just for completeness, see link; 
http://docs.python.org/library/threading.html

" ... an import should not have the side effect of spawning a new thread
and then waiting for that thread in any way..."


-- 

DaveA





More information about the Python-list mailing list