On 3/5/2016 6:45 AM, Christian Gollwitzer wrote:
Am 05.03.16 um 11:15 schrieb Terry Reedy:
On 3/5/2016 2:52 AM, Christian Gollwitzer wrote:
is there an easy way to add an application console to a Tkinter program?
Right now, you should turn the question around.
so this means no, right?
Right.
Is there an easy way to
run a tkinter program within an interactive console? Answer: yes, two
ways, after removing the runshell stuff and mainloop call*.
1. Call your program mytk.py. In your system console, run 'python -i
myth.py'. When the code ends, control passes to the console running
python. Statements like 'print(nvar.get())' will be executed in the
main namespace of the still running program.
well yes, this does work, but I should have explained why I want it the
other way round. We have an in-house tool which is used to manipulate
images. During production use, at some point you think "and now if I
could just save the image that I see on screen into a PNG file". You
know exactly that MyViewer.image is the thing that contains what you
need, if only you had a way to tell it
'MyViewer.image.save("somewhere.png")'. At this point, you haven't
started the program from an interactive python. Always running the tool
from ipython or idle means there are useless windows hanging around, but
if you close them, your pogram goe away. To make it even more
complicated, the deployed version of the tool uses pyinstaller to be
safe from environment changes.
Since idlelib.PyShell is the idle startup module as well Shell window
module, importing it imports practically all of idlelib. Not what you
want. Calling PyShell.main calls tk.Tk and tk.mainloop, also not what
you want.
Of course, I could pack some text widget somewhere and fiddle a few
bindings to make it do this with eval(), but a good REPL has history,
autocompletion, syntax highlighting.... you get it. I had simply hoped,
since idle is written in Tkinter, that it could be reused for that purpose.
(For statements, you would use exec() rather than eval().)
Not now. A console is a REPL + text display to read from and print to.
The actual IDLE REPL is PyShell.ModifiedInterpreter, which subclasses
stdlib code.InteractiveInterpreter. Most of the additions are for
interacting with the subprocess that runs user code. You should start
instead with the base class.
The Shell text display is a subclass of a subclass of a class that
contains a subclass of Toplevel with the complete IDLE Menu and a Text
widget wrapper. Again, this is too much baggage for an application console.
The idlelib ColorDelegator syntax highlighter can be reused with a Text
instance. See turtledemo.__main__ for an example. I don't know if (or
how) IDLE's autocompletion modules could be reused in their current
state. I believe Shell's history 'list' consists of the statements in
the Text instance prefixed by the '>>> ' prompt.
A simple app console might have separate text boxes for input and output.
For pure Tcl/Tk, there is tkcon which can do exactly this and I use it
in similar tools writtin in Tcl/Tk. I can run it via Tk.eval(), but I
couldn't find a way to call back into Python coming from the Tkinter
interpreter, and obviously autocompletion and syntax highlighting do not
work well.
For instance, can you embed IDLE into a program such that when a button
is pressed, it pops up a REPL window where the running program can be
examined?
If the REPL window is defined in an imported module, the problem is
linking the main namespace of the tkinter program with the REPL loop in
such a way that commands entered into the REPL are executed in the main
module, not in the REPL module.
I'm happy to pass the main module as an argument to REPLInit().
2) If you click the Shell button twice, it locks up the program, because
main() obviously starts it's own mainloop
IDLE executes user code in a separate process, linked by sockets, so
that execution of IDLE GUI code and user code do not interfere with each
other.
Ahhh - OK this makes sense in the general case, but not for a console
where you *want* your REPL to perform surgery on the main program.
I would like to refactor IDLE so that the Shell window
...
It might be possible to adapt such a component as an embedded console.
An imported frame should not interfere with the main-module code or code
in other modules. The main problems are a) namespace linkage (mentioned
before),
Perhaps I should have said 'issues that require attention' rather than
'problems' ;-). As you note, b) and c) are conceptually easy, though
the execution in IDLE is complicated by having to communicate between
two processes. The execution in a within-process console would be much
easier.
b) the need for sys.stdin/out/err to not be None,
tkcon solves this be redirecting stdin/stdout/stderr to functions which
write to the console window.
IDLE sets sys.stdin, etc, in the user process to custom instances with
read/write methods.
and c) for
capturing exceptions in code entered in the console, so as to not crash
the main program.
For Python exceptions I see no problem - the eval must simply be
properly wrapped in try..except and the traceback is redirected to the
console.
--
Terry Jan Reedy
--
https://mail.python.org/mailman/listinfo/python-list