5

I'm using the following python code to embed a terminal window (from Ubuntu Linux) in a Tkinter window. I would like give the command 'sh kBegin' in the window automatically when the terminal window starts:

from Tkinter import *
from os import system as cmd

root = Tk()
termf = Frame(root, height=800, width=1000)

termf.pack(fill=BOTH, expand=YES)
wid = termf.winfo_id()
cmd('xterm -into %d -geometry 160x50 -sb &' % wid)

root.mainloop()

Pseudo:

cmd('xterm -into %d -geometry 160x50 -sb &' % wid)
embedded_terminal('sh kBegin')
# EMBEDDED TERMINAL DISPLAYS OUTPUT OF sh kBegin##

How would I get this working?

nbro
  • 15,395
  • 32
  • 113
  • 196
abkai
  • 591
  • 2
  • 6
  • 18
  • If you don't need to interact at all, you could use: `xterm -into ... -sb -hold -e sh kBegin` – mgilson Apr 20 '12 at 04:11
  • @mgilson thanks, but I do need to interact with the terminal and it returned an error using the -font tag as well: "xterm -font -adobe-courier-medium-r-normal--18-180-75-75-m-110-iso8859-1 -into %d -geometry 88x37 -sb -hold -e sh kBegin". I need to be able to send commands from say.. A button press in Tkinter enters the text "Hello World && " into the terminal. Thanks for your help! :) – abkai Apr 20 '12 at 04:28
  • If you can do that, I'm quite interested in the solution as well! I've often wondered if it's possible to embed an arbitrary x11 window inside a tkinter widget ... I think that would be pretty nifty too... – mgilson Apr 20 '12 at 04:31
  • This gets you a little further: `xterm ... -e "sh kBegin;bash"`, but not much. I'm not sure if you're going to get much further though... (reference) http://www.gossamer-threads.com/lists/python/python/669765 – mgilson Apr 20 '12 at 04:44
  • @mgilson Haha sweet, if I do manage to get anywhere; I'll let you know. I may end up just resorting to a more powerful gui kit, as I don't seem to be having any luck at all (except for what you just suggested). I did manage to set something up using sockets and multiple threads; it just feels a little pointless having to do that. – abkai Apr 20 '12 at 04:44
  • see also [tkterminal](https://github.com/Saadmairaj/tkterminal), a Terminal widget for Tkinter – milahu Apr 06 '22 at 02:35

1 Answers1

8

You can interact with a shell by writing in the pseudo-terminal slave child. Here is a demo of how it could works. This answer is somewhat based on an answer to Linux pseudo-terminals: executing string sent from one terminal in another.

The point is to get the pseudo-terminal used by xterm (through tty command) and redirect output and input of your method to this pseudo-terminal file. For instance ls < /dev/pts/1 > /dev/pts/1 2> /dev/pts/1

Note that

  1. xterm child processed are leaked (the use of os.system is not recommended, especially for & instructions. See suprocess module).
  2. it may not be possible to find programmatically which tty is used
  3. each commands are executed in a new suprocess (only input and output is displayed), so state modification command such as cd have no effect, as well as context of the xterm (cd in the xterm)

from Tkinter import *
from os import system as cmd

root = Tk()
termf = Frame(root, height=700, width=1000)
termf.pack(fill=BOTH, expand=YES)
wid = termf.winfo_id()

f=Frame(root)
Label(f,text="/dev/pts/").pack(side=LEFT)
tty_index = Entry(f, width=3)
tty_index.insert(0, "1")
tty_index.pack(side=LEFT)
Label(f,text="Command:").pack(side=LEFT)
e = Entry(f)
e.insert(0, "ls -l")
e.pack(side=LEFT,fill=X,expand=1)

def send_entry_to_terminal(*args):
    """*args needed since callback may be called from no arg (button)
   or one arg (entry)
   """
    command=e.get()
    tty="/dev/pts/%s" % tty_index.get()
    cmd("%s <%s >%s 2> %s" % (command,tty,tty,tty))

e.bind("<Return>",send_entry_to_terminal)
b = Button(f,text="Send", command=send_entry_to_terminal)
b.pack(side=LEFT)
f.pack(fill=X, expand=1)

cmd('xterm -into %d -geometry 160x50 -sb -e "tty; sh" &' % wid)

root.mainloop()
Community
  • 1
  • 1
FabienAndre
  • 4,514
  • 25
  • 38
  • Wow! That worked perfectly! Thanks heaps! I'm going to have a play around with what you provided, and manifest it to work to my needs. But that instance worked spot on. Thank you :) – abkai Apr 25 '12 at 11:36