
And I *do* face a crucial functional issue with TK, and only on Linux, as it happens, regarding threading.
I may try to present the issue later, to try to get some feedback, and help determine whether the issue is inherent, a limitation of the developer, or a limitation of the particular toolkit.
Here goes: So I have 2 windows - one is a Display for the VPython rendering and is actually constructed as a class derived from the VPython display object (native on Windows, GTK1 on linux) The other is a TK control panel. The user can interact with either - pick and move points, for example, in the Display, or reveal or hide construction levels from the control Panel. So each must be in a loop, and the 2 windows need to be able to communicate with to each other as to any user action. On Windows, in the Display class I create the Panel, sending the Display as one of the arguments, while saving a reference to the Panel as an attribute of the Display class. And start a thread that sets off the TK loop for the Panel. The Display now has a reference to the Panel set on its creation, and the Panel now has a reference to the Display, sent to it as an argument. And the communication is bi-directional, via these references. Same tact on Linux produces an error something to the effect: "Attempt to start TK instance from a separate appartment" (definitely spelled with 2 p's). A search on this error message on python-list brings me to a post by Aahz, resident threading expert, asking why one would want to multi-thread a TK application. Implying, I think, that one can't. I am not sure that I need to. Or mean to. But nonetheless I can't find an approach here that yields bi-directional messaging other than the one that works on Windows. This is sounding both esoteric, and not well described. But I am not so much expecting as answer, as much as anyone's gut as to whether this is answerable, and whether my problem is in any way TK specific. Thanks. Art

So Tim has joined us for a spell. This is the student who did the calendar cgi I mentioned awhile back. I've been serving as his mentor via Saturday Academy. Tim, now in 8th grade, has been learning Python, amidst other explorations having to do with an Independent Learning Project (ILP). Feel free to ask him for more details if curious. And for sure visit his web site: http://kmg.is-a-geek.org/ (he's hosting this from his family computer through dyndns, so you'll almost literally be a guest in his home). Kirby

Arthur wrote:
So I have 2 windows - one is a Display for the VPython rendering and is actually constructed as a class derived from the VPython display object (native on Windows, GTK1 on linux) The other is a TK control panel.
The user can interact with either - pick and move points, for example, in the Display, or reveal or hide construction levels from the control Panel. So each must be in a loop, and the 2 windows need to be able to communicate with to each other as to any user action.
I don't understand what the loop is doing. It sounds like you are polling the panel for changes instead of using event callbacks and the GUI event loop. Maybe you know this - normally in a GUI application you register callback handlers with the widgets in the gui. So when a field changes a handler function is called to do whatever you want. No explicit loop is needed. You certainly should be able to create a GUI app with two panels that respond to user input without explicitly creating any threads. HTH Kent
On Windows, in the Display class I create the Panel, sending the Display as one of the arguments, while saving a reference to the Panel as an attribute of the Display class. And start a thread that sets off the TK loop for the Panel. The Display now has a reference to the Panel set on its creation, and the Panel now has a reference to the Display, sent to it as an argument. And the communication is bi-directional, via these references.
Same tact on Linux produces an error something to the effect:
"Attempt to start TK instance from a separate appartment" (definitely spelled with 2 p's).
A search on this error message on python-list brings me to a post by Aahz, resident threading expert, asking why one would want to multi-thread a TK application. Implying, I think, that one can't.
I am not sure that I need to. Or mean to. But nonetheless I can't find an approach here that yields bi-directional messaging other than the one that works on Windows.
This is sounding both esoteric, and not well described. But I am not so much expecting as answer, as much as anyone's gut as to whether this is answerable, and whether my problem is in any way TK specific.
Thanks.
Art
_______________________________________________ Edu-sig mailing list Edu-sig@python.org http://mail.python.org/mailman/listinfo/edu-sig

Kent writes -
Arthur wrote:
So I have 2 windows - one is a Display for the VPython rendering and is actually constructed as a class derived from the VPython display object (native on Windows, GTK1 on linux) The other is a TK control panel.
The user can interact with either - pick and move points, for example, in the Display, or reveal or hide construction levels from the control Panel. So each must be in a loop, and the 2 windows need to be able to communicate with to each other as to any user action.
I don't understand what the loop is doing. It sounds like you are polling the panel for changes instead of using event callbacks and the GUI event loop.
Maybe you know this - normally in a GUI application you register callback handlers with the widgets in the gui. So when a field changes a handler function is called to do whatever you want. No explicit loop is needed.
I am not sure what you are saying. By "be in a loop" I think I am referring to the same GUI event loop to which you are referring. My TK "loop" is nothing but the GUI event loop, using the event callbacks,
You certainly should be able to create a GUI app with two panels that respond to user input without explicitly creating any threads.
I think I understand that this is trivial, when the two panels of the GUI app are using the same GUI toolkit. That is specifically the kind of thing that GUI toolkits are designed to handle, and why Aahz asks why someone would want to multi-thread a TK application. And the fact is I don't want to multi-thread a TK application. What I want is a single TK thread and a single GTK thread, and the capacity to communicate between them, bi-directionally. Well, this is not really what I want;) But it is the problem that the circumstances put on my plate, as I am interpreting the circumstances and the problem. How could I have 2 windows from 2 different windowing toolkits, each responsive to user interaction, without running them as separate threads? Then I have also heard it said, as an opinion, that threading is usually the wrong solution for communication between processes. But when we get into to the distinction between separate processes and separate threads, I am in territory with which I am unfamiliar. The problem of running the old IDLE with VPython was, I think, one of making room for two processes, rather than 2 threads to run, without interference. And it was solved. Using sockets? But then, in this case, no input to IDLE needs to be handled *while* a VPython window runs. So I think my problem is distinguished. All that said, I am not *convinced* that there is not a trivial solution here. The solution on Windows is trivial enough. But my assumption that it was a crossplatform solution, at least as to the specifics of my implementation, was apparently naïve. Art

Thanks for the explanation. I didn't realize that the two panels are using different GUI frameworks. I don't know how to make that work... Kent Arthur wrote:
Kent writes -
Arthur wrote:
So I have 2 windows - one is a Display for the VPython rendering and is actually constructed as a class derived from the VPython display object (native on Windows, GTK1 on linux) The other is a TK control panel.
The user can interact with either - pick and move points, for example,
in
the Display, or reveal or hide construction levels from the control
Panel.
So each must be in a loop, and the 2 windows need to be able to
communicate
with to each other as to any user action.
I don't understand what the loop is doing. It sounds like you are polling the panel for changes instead of using event callbacks and the GUI event loop.
Maybe you know this - normally in a GUI application you register callback handlers with the widgets in the gui. So when a field changes a handler function is called to do whatever you want. No explicit loop is needed.
I am not sure what you are saying. By "be in a loop" I think I am referring to the same GUI event loop to which you are referring. My TK "loop" is nothing but the GUI event loop, using the event callbacks,
You certainly should be able to create a GUI app with two panels that respond to user input without explicitly creating any threads.
I think I understand that this is trivial, when the two panels of the GUI app are using the same GUI toolkit. That is specifically the kind of thing that GUI toolkits are designed to handle, and why Aahz asks why someone would want to multi-thread a TK application.
And the fact is I don't want to multi-thread a TK application. What I want is a single TK thread and a single GTK thread, and the capacity to communicate between them, bi-directionally.
Well, this is not really what I want;) But it is the problem that the circumstances put on my plate, as I am interpreting the circumstances and the problem.
How could I have 2 windows from 2 different windowing toolkits, each responsive to user interaction, without running them as separate threads?
Then I have also heard it said, as an opinion, that threading is usually the wrong solution for communication between processes. But when we get into to the distinction between separate processes and separate threads, I am in territory with which I am unfamiliar.
The problem of running the old IDLE with VPython was, I think, one of making room for two processes, rather than 2 threads to run, without interference. And it was solved. Using sockets? But then, in this case, no input to IDLE needs to be handled *while* a VPython window runs. So I think my problem is distinguished.
All that said, I am not *convinced* that there is not a trivial solution here. The solution on Windows is trivial enough. But my assumption that it was a crossplatform solution, at least as to the specifics of my implementation, was apparently naïve.
Art

Kent writes -
Thanks for the explanation. I didn't realize that the two panels are using different GUI frameworks. I don't know how to make that work...
Kent
Well, that's 2 of us anyway ;) I'm suspecting that I will have more flexibility when VPython moves from GTK1 to GTK2. But that might too, be wrong. FWIW, Arnd had recently mentioned coming to a solution that included the ipython interactive shell, when Idle could not serve his needs - because of its use of sockets. It turns out I can't use ipython to serve my needs with VPython, because it suffers from the same disease as did the old Idle - and which Idle solved with the use of sockets. It closes when I close a VPython display Life sucks ;) Art

Arthur, In our VR work here, we do something very similar to what you are doing, but in an impoverished way. We use a Tk panel to control simulations in VPython. We have done this using threads and run on both Linux (our primary platform) and Windows with no hitch. The main difference, I think, is that we are not trying to communicate back from VPython to the Tk panel. We can spin and zoom in the Vpython window, and control other parameters through Tk. I guess I don't see any reason in principle that the two-way communication shouldn't work. I suspect, can't tell without digging into your code, that the problem is that you end up making Tk calls from two different threads. That is strictly a no-no. It used to be the case that Tk calls could only be made in the thread that did the Tkinter import. I think that it's now OK to import, but only make calls in the thread the creates the main app (calls Tk() to get the root widget). If you are not currently doing this, the next step to try is to create the Tk interface in main program, and have that initial program call the Tk mainloop. That means that the VPython stuff will actually be created and run in the separate thread. As long as mainloop() is in your initial thread (the one that imports Tkinter and grabs Tk()), I think that your approach will work under Linux and Windows. If I get a little free time (hah!, it's finals week) I might try putting together a little demo to see that this two-way communication works. By the way, I hope you are using locks to protect any shared data across the two threads. --John Arthur wrote:
Kent writes -
Thanks for the explanation. I didn't realize that the two panels are using different GUI frameworks. I don't know how to make that work...
Kent
Well, that's 2 of us anyway ;)
I'm suspecting that I will have more flexibility when VPython moves from GTK1 to GTK2. But that might too, be wrong.
FWIW, Arnd had recently mentioned coming to a solution that included the ipython interactive shell, when Idle could not serve his needs - because of its use of sockets.
It turns out I can't use ipython to serve my needs with VPython, because it suffers from the same disease as did the old Idle - and which Idle solved with the use of sockets. It closes when I close a VPython display
Life sucks ;)
Art
_______________________________________________ Edu-sig mailing list Edu-sig@python.org http://mail.python.org/mailman/listinfo/edu-sig

We have multiple threads interacting with a Tk window (Pyro Robotics). But it has proven very reliable---even without any locks of any sort. I did make sure that we only have one Tk interpreter; it is easy to accidently create more than one. One situation does fail relably, however: on machines that have multiple processors, it seems that the Tk update code often steps on itself. I have tried to come up with a stripped-down example of the failure, but alas have not been able to pinpoint the problem. -Doug John Zelle wrote:
Arthur,
In our VR work here, we do something very similar to what you are doing, but in an impoverished way. We use a Tk panel to control simulations in VPython. We have done this using threads and run on both Linux (our primary platform) and Windows with no hitch. The main difference, I think, is that we are not trying to communicate back from VPython to the Tk panel. We can spin and zoom in the Vpython window, and control other parameters through Tk. I guess I don't see any reason in principle that the two-way communication shouldn't work.
I suspect, can't tell without digging into your code, that the problem is that you end up making Tk calls from two different threads. That is strictly a no-no. It used to be the case that Tk calls could only be made in the thread that did the Tkinter import. I think that it's now OK to import, but only make calls in the thread the creates the main app (calls Tk() to get the root widget).
If you are not currently doing this, the next step to try is to create the Tk interface in main program, and have that initial program call the Tk mainloop. That means that the VPython stuff will actually be created and run in the separate thread. As long as mainloop() is in your initial thread (the one that imports Tkinter and grabs Tk()), I think that your approach will work under Linux and Windows.
If I get a little free time (hah!, it's finals week) I might try putting together a little demo to see that this two-way communication works. By the way, I hope you are using locks to protect any shared data across the two threads.
--John
Arthur wrote:
Kent writes -
Thanks for the explanation. I didn't realize that the two panels are using different GUI frameworks. I don't know how to make that work...
Kent
Well, that's 2 of us anyway ;)
I'm suspecting that I will have more flexibility when VPython moves from GTK1 to GTK2. But that might too, be wrong.
FWIW, Arnd had recently mentioned coming to a solution that included the ipython interactive shell, when Idle could not serve his needs - because of its use of sockets.
It turns out I can't use ipython to serve my needs with VPython, because it suffers from the same disease as did the old Idle - and which Idle solved with the use of sockets. It closes when I close a VPython display
Life sucks ;)
Art
_______________________________________________ Edu-sig mailing list Edu-sig@python.org http://mail.python.org/mailman/listinfo/edu-sig
_______________________________________________ Edu-sig mailing list Edu-sig@python.org http://mail.python.org/mailman/listinfo/edu-sig
-- Douglas S. Blank, Assistant Professor dblank@brynmawr.edu, (610)526-6501 Bryn Mawr College, Computer Science Program 101 North Merion Ave, Park Science Bld. Bryn Mawr, PA 19010 dangermouse.brynmawr.edu

Doug, John, Tim, etal Thanks for helping me kick this around. Bottom line problem is that I am using threading without understanding threads. I'm guessing my answer is somewhere in getting down a level into the threads themselves, rather than trying to get away with only dealing at the level of the objects being threaded. And now that I have a real problem to solve, I'll probably get down there (eventually) and solve it Like most of us, I'm sure, almost anything I understand about programming I understand because I needed to understand it to solve a real problem. Even if the problem is one self-imposed - like the PyGeo project. But this is part of the reason that I think that the answer to the question of more general programming literacy has to do with curricula integration. To most students pursuing higher education, at least, the need to get their mind around the concepts of, say, Calculus is a real problem. They have not chosen that problem any more than I have chosen the problem of threading. It has chosen them. They have to understand Calculus. I think that understanding a bit about programming can help them solve that problem, and others of the kind. And it only at the point that they are solving *real* problems, even if only for themselves, that they can get the sense of what it is to program and be a programmer. Art
-----Original Message----- From: Douglas S. Blank [mailto:dblank@brynmawr.edu] Sent: Wednesday, December 15, 2004 12:16 PM To: John Zelle Cc: Arthur; edu-sig@python.org Subject: Re: [Edu-sig] re: Pygeo, platforms, wx and Tk
We have multiple threads interacting with a Tk window (Pyro Robotics). But it has proven very reliable---even without any locks of any sort. I did make sure that we only have one Tk interpreter; it is easy to accidently create more than one.
One situation does fail relably, however: on machines that have multiple processors, it seems that the Tk update code often steps on itself. I have tried to come up with a stripped-down example of the failure, but alas have not been able to pinpoint the problem.
-Doug
Arthur,
In our VR work here, we do something very similar to what you are doing, but in an impoverished way. We use a Tk panel to control simulations in VPython. We have done this using threads and run on both Linux (our primary platform) and Windows with no hitch. The main difference, I think, is that we are not trying to communicate back from VPython to the Tk panel. We can spin and zoom in the Vpython window, and control other parameters through Tk. I guess I don't see any reason in principle that the two-way communication shouldn't work.
I suspect, can't tell without digging into your code, that the problem is that you end up making Tk calls from two different threads. That is strictly a no-no. It used to be the case that Tk calls could only be made in the thread that did the Tkinter import. I think that it's now OK to import, but only make calls in the thread the creates the main app (calls Tk() to get the root widget).
If you are not currently doing this, the next step to try is to create the Tk interface in main program, and have that initial program call the Tk mainloop. That means that the VPython stuff will actually be created and run in the separate thread. As long as mainloop() is in your initial thread (the one that imports Tkinter and grabs Tk()), I think that your approach will work under Linux and Windows.
If I get a little free time (hah!, it's finals week) I might try putting together a little demo to see that this two-way communication works. By the way, I hope you are using locks to protect any shared data across the two threads.
--John
Arthur wrote:
Kent writes -
Thanks for the explanation. I didn't realize that the two panels are using different GUI frameworks. I don't know how to make that work...
Kent
Well, that's 2 of us anyway ;)
I'm suspecting that I will have more flexibility when VPython moves from GTK1 to GTK2. But that might too, be wrong.
FWIW, Arnd had recently mentioned coming to a solution that included
John Zelle wrote: the
ipython interactive shell, when Idle could not serve his needs - because of its use of sockets.
It turns out I can't use ipython to serve my needs with VPython, because it suffers from the same disease as did the old Idle - and which Idle solved with the use of sockets. It closes when I close a VPython display
Life sucks ;)
Art
_______________________________________________ Edu-sig mailing list Edu-sig@python.org http://mail.python.org/mailman/listinfo/edu-sig
_______________________________________________ Edu-sig mailing list Edu-sig@python.org http://mail.python.org/mailman/listinfo/edu-sig
-- Douglas S. Blank, Assistant Professor dblank@brynmawr.edu, (610)526-6501 Bryn Mawr College, Computer Science Program 101 North Merion Ave, Park Science Bld. Bryn Mawr, PA 19010 dangermouse.brynmawr.edu

Arthur wrote:
Like most of us, I'm sure, almost anything I understand about programming I understand because I needed to understand it to solve a real problem.
This is actually a learning style question. I am personally only happy working on a system when I "understand" the layer below it. This is why I dislike windows (the system I primarily use) so much, and why I have so many issues with GUI programming -- I have a hard time letting go and "letting it be magic." Lucky for me I started with an ancient computer (the LGP-30); there was something comforting about looking at discrete components and boards of diodes with present and missing diodes.
... it only at the point that they are solving *real* problems, even if only for themselves, that they can get the sense of what it is to program and be a programmer.
Actually, for me, the "real problem" is second. I need a "real problem" to test whether I really understand an idea, or only think I do. I often have to loop back around a time or two to "get" it.
... Bottom line problem is that I am using threading without understanding threads. I'm guessing my answer is somewhere in getting down a level into the threads themselves, rather than trying to get away with only dealing at the level of the objects being threaded.
If you have a concrete understanding of processes, try this idea for threads: the old idea of a process as a separate "machine" can be split into two ideas: a resource allocation entity (for virtual memory, file handles, security ...) which there is one of per process, and a schedulable entity (which owns as little as possible) living inside a process that determines what the CPU does next. The latter of these two is called a "thread of execution" (hence thread). Multi-thread programming is simply multiprocess programming with all of the safety protection between the separate processes turned off. Sharing memory between threads is easy (they all live in the same memory space), but dangerous, because the different threads can be interwoven at the finest granularity available on the machine. So, sharing data that everyone reads is simple, but negotiating when a write is seen by another thread requires planning. Usually this is done by arranging that each thread plays in its own area, and writes (often through queues) when the data is available for others to read. A nasty complication to your intuition in threaded programming is that things you thought were indivisible operations are so only from the point of view of the thread performing the operation; often they have parts that another thread can see in the half-completed view. Python is lucky in that many python writes look like either: a) get a reference to a data structure (python object reference) and store it somewhere, an operation that _is_ indivisible. or b) build a data structure which was formerly non-existent (and therefore not shared with anyone else) and store a single pointer to it, an operation that _is_ indivisible. both of these work fine in a threaded environment. However, operations like list.reverse() have intermediate states. So, for a list "data" built like: data = range(1000000) is examined by two threads, one of which is doing sum(data), and the other of which is doing data.reverse(), the totals of the summing thread can vary substantially. -- -- Scott David Daniels Scott.Daniels@Acm.Org

From: Arthur <ajsiegel@optonline.net>
So I have 2 windows - one is a Display for the VPython rendering and is actually constructed as a class derived from the VPython display object (native on Windows, GTK1 on linux) The other is a TK control panel.
Hi. I'm new here. Now we have two Tim's. I've run into the duelling event loop scenario before, but not with these specific toolkits. The solution then was to refactor a bit and arrange to have one event loop, rather than having multiple threads. To implement a similar solution in this case, you would have to find the entry point that processes one GTK event, and another entrypoint that processes one TK event, then you do something like this: while True: get an event if the event came from the TK window: process it as a TK event else: process it as a GTK event Unfortunately, I suspect you'll lose OS portability when you do that, since the base events are different sorts of things for MSWindows and X Windows. The bad solution I encountered before had two threads with independent event loops. The symptom then was that events would occasionally get ignored when the event loop in wrong thread picked them up and didn't know what to do with them. Another solution would be to have two completely separate processes, each with its own connection to the window system. This way each event loop is guaranteed to get the events from the right window. Whether this is possible for you depends on whether it's feasible for your GTK and your TK code to interact the way you want when they are in separate processes. -- Tim Freeman http://www.fungible.com tim@fungible.com Programmer/consultant in the Sunnyvale, CA area. I'm presently available.
participants (7)
-
Arthur
-
Douglas S. Blank
-
John Zelle
-
Kent Johnson
-
Kirby Urner
-
Scott David Daniels
-
Tim Freeman