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