Python Forum
Tkinter Shell Terminal Or Shell Output
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Tkinter Shell Terminal Or Shell Output
#1
Hello all,

New at using Python here, I have a bash script that I used to automate tasks on my home NAS/Server running Archlinux and I have decided to make it better and dive into Python whilst I have the time, unfortunately.

Anyway, I have successfully created the code and a GUI using Tkinter. All is working as it should (same as was my bash script) However, I wanted to make some improvement and want to have the shell output of the command being display within the GUI depending on which action/command the GUI is being asked to perform.

I.E. at the moment, I am running Mnamer from the GUI to analysed my Download folder within my NAS/Server to detect TV Show / Movies downloaded that moves it to the right folder and rename it also. I would like the shell output to be displayed within the GUI window to make sure that the right tv show or movie has been detected instead of having to navigate the folders.

Even better, would be to have access to the shell terminal within the GUI window, in order to send command when I use the GUI to connect via SSH to my nas / server or my kid computer?

Other commands would just remain as current with a successful window popping up.

See Below the script - any advice help would be appreciated.

import subprocess
from tkinter import *
from tkinter import messagebox
from tkinter import ttk

window = Tk()

#modify window
window.title("Server Commander")
window.geometry("228x400")

tab_control = ttk.Notebook(window)

#Creating tabs
tab1 = ttk.Frame(tab_control)
tab2 = ttk.Frame(tab_control)

#Modifying tabs
tab_control.add(tab1, text='Server')
tab_control.add(tab2, text='Computer')

#Creating button & actions
#Tab Server
def issue():
    subprocess.call('ssh [email protected] sudo systemctl start pyload', shell=True)
    messagebox.showinfo('Start PyLoad', 'PyLoad Started successfully!')
btn = Button(tab1, text="Start Pyload", command=issue)
btn.grid(column=1, row=5, sticky='news')

def issue():
    subprocess.call("ssh [email protected] sudo systemctl stop pyload", shell=True)
    messagebox.showinfo('Stop PyLoad', 'Pyload Stopped successfully!')
btn = Button(tab1, text="Stop PyLoad", command=issue)
btn.grid(column=2, row=5, sticky='news')

def issue():
    subprocess.call("ssh [email protected] python -m mnamer -bvr /mnt/hd/Download/", shell=True)
    messagebox.showinfo('Mnamer', 'Mnamer successfully!')
btn = Button(tab1, text="Mnamer", command=issue)
btn.grid(column=1, row=6, sticky='news')

def issue():
    subprocess.call("ssh [email protected] /usr/local/sbin/extractall.sh", shell=True)
    messagebox.showinfo('Extract Files', 'Extract Files successfully!')
btn = Button(tab1, text="Extract Files", command=issue)
btn.grid(column=1, row=7, sticky='news')

def issue():
    subprocess.call("ssh [email protected] rm /mnt/hd/Download/*.rar", shell=True)
    messagebox.showinfo('Remove Rar', 'Remove Rar successfully!')
btn = Button(tab1, text="Remove Rar", command=issue)
btn.grid(column=2, row=7, sticky='news')

def issue():
    subprocess.call("deepin-terminal -e ssh [email protected]", shell=True)
    messagebox.showinfo('SSH GoFlex', 'SSH GoFlex successfully!')
btn = Button(tab1, text="SSH GoFlex", command=issue)
btn.grid(column=1, row=8, sticky='news')

def issue():
    subprocess.call("deepin-terminal -e ssh [email protected]", shell=True)
    messagebox.showinfo('SSH Paco', 'SSH Paco successfully!')
btn = Button(tab1, text="SSH Paco", command=issue)
btn.grid(column=2, row=8, sticky='news')

def issue():
    subprocess.call("sudo -u sweetth mount /mnt/share && dde-file-manager /mnt/share/", shell=True)
    messagebox.showinfo('Mount GoFlex', 'Mount GoFlex successfully!')
btn = Button(tab1, text="Mount GoFlex", command=issue)
btn.grid(column=1, row=9, sticky='news')

def issue():
    subprocess.call("sudo umount /mnt/share", shell=True)
    messagebox.showinfo('Umount GoFlex', 'Umount GoFlex successfully!')
btn = Button(tab1, text="Umount GoFlex", command=issue)
btn.grid(column=2, row=9, sticky='news')

def issue():
    subprocess.call("ssh [email protected] sudo systemctl reboot", shell=True)
    messagebox.showinfo('Reboot NAS', 'Reboot NAS successfully!')
btn = Button(tab1, text="Reboot NAS", command=issue)
btn.grid(column=1, row=10, sticky='news')

def issue():
    subprocess.call("ssh [email protected] sudo systemctl poweroff", shell=True)
    messagebox.showinfo('Power Off NAS', 'Power Off NAS successfully!')
btn = Button(tab1, text="Power Off NAS", command=issue)
btn.grid(column=2, row=10, sticky='news')

#Tab Computer
def issue():
    subprocess.call('sudo systemctl start pyload', shell=True)
    messagebox.showinfo('Start PyLoad', 'PyLoad Started successfully!')
btn = Button(tab2, text="Start PyLoad", command=issue)
btn.grid(column=1, row=5, sticky='news')

def issue():
    subprocess.call("sudo systemctl stop pyload", shell=True)
    messagebox.showinfo('Stop PyLoad', 'Pyload Stopped successfully!')
btn = Button(tab2, text="Stop PyLoad", command=issue)
btn.grid(column=2, row=5, sticky='news')

tab_control.pack(expand=1, fill='both')

#event loop
window.mainloop()
Reply
#2
because you are using a subprocess, the output will be going to stdout (errors to stderr)
you can redirect stdout and stderr so that it will go to a file (or buffer in memory)
example to file:
savefile = full_filepath
hold_stdout = sys.stdout
sys.stdout = open(savefile, 'w')
# all stdout will be written to file
# when done, reset stdout so that you will see srcipt output:
sys.stdout = hold_stdout
This should work, but I haven't tested (but used something very similar in the past)

You can redirect stderr in a similar fashion.
Reply
#3
Firstly thank you so much for taking the time to read my topic and your reply.

I am just starting with Python and I must admit I am struggling to adapt your code to my script.

I incorporated your code to the file (see below) but I can't figure out how to pass it on to each command for it to record onto the file.

p.s. I added a scrolleldtext to display the result once I have figured the above.

Again, thank you for your time and patience

import subprocess
from tkinter import *
from tkinter import messagebox
from tkinter import ttk
from tkinter import scrolledtext
import sys

window = Tk()

#Write terminal output to file
savefile = '/home/sweetth/PycharmProjects/pythonProject/stdout.txt'
hold_stdout = sys.stdout
sys.stdout = open(savefile, 'w')
sys.stdout = hold_stdout

#modify window
window.title("Server Commander")
window.geometry("600x350")

tab_control = ttk.Notebook(window)

#Creating tabs
tab1 = ttk.Frame(tab_control)
tab2 = ttk.Frame(tab_control)

#Modifying tabs
tab_control.add(tab1, text='Server')
tab_control.add(tab2, text='Computer')

#Creating button & actions
#Tab Server
def issue():
    subprocess.run('ssh [email protected] sudo systemctl start pyload', shell=True)
    messagebox.showinfo('Start PyLoad', 'PyLoad Started successfully!')
btn = Button(tab1, text="Start Pyload", command=issue, height=1, width=12)
btn.grid(column=1, row=5, sticky='news')

def issue():
    subprocess.run("ssh [email protected] sudo systemctl stop pyload", shell=True)
    messagebox.showinfo('Stop PyLoad', 'Pyload Stopped successfully!')
btn = Button(tab1, text="Stop PyLoad", command=issue, height=1, width=12)
btn.grid(column=2, row=5, sticky='news')

def issue():
    subprocess.run("ssh [email protected] python -m mnamer -bvr /mnt/hd/Download/", shell=True)
    messagebox.showinfo('Mnamer', 'Mnamer successfully!')
btn = Button(tab1, text="Mnamer", command=issue, height=1, width=12)
btn.grid(column=1, row=6, sticky='news')

def issue():
    subprocess.run("ssh [email protected] /usr/local/sbin/extractall.sh", shell=True)
    messagebox.showinfo('Extract Files', 'Extract Files successfully!')
btn = Button(tab1, text="Extract Files", command=issue, height=1, width=12)
btn.grid(column=1, row=7, sticky='news')

def issue():
    subprocess.run("ssh [email protected] rm /mnt/hd/Download/*.rar", shell=True)
    messagebox.showinfo('Remove Rar', 'Remove Rar successfully!')
btn = Button(tab1, text="Remove Rar", command=issue, height=1, width=12)
btn.grid(column=2, row=7, sticky='news')

def issue():
    subprocess.run("deepin-terminal -e ssh [email protected]", shell=True)
    messagebox.showinfo('SSH GoFlex', 'SSH GoFlex successfully!')
btn = Button(tab1, text="SSH GoFlex", command=issue, height=1, width=12)
btn.grid(column=1, row=8, sticky='news')

def issue():
    subprocess.run("deepin-terminal -e ssh [email protected]", shell=True)
    messagebox.showinfo('SSH Paco', 'SSH Paco successfully!')
btn = Button(tab1, text="SSH Paco", command=issue, height=1, width=12)
btn.grid(column=2, row=8, sticky='news')

def issue():
    subprocess.run("sudo -u sweetth mount /mnt/share && dde-file-manager /mnt/share/", shell=True)
    messagebox.showinfo('Mount GoFlex', 'Mount GoFlex successfully!')
btn = Button(tab1, text="Mount GoFlex", command=issue, height=1, width=12)
btn.grid(column=1, row=9, sticky='news')

def issue():
    subprocess.run("sudo umount /mnt/share", shell=True)
    messagebox.showinfo('Umount GoFlex', 'Umount GoFlex successfully!')
btn = Button(tab1, text="Umount GoFlex", command=issue, height=1, width=12)
btn.grid(column=2, row=9, sticky='news')

def issue():
    subprocess.run("ssh [email protected] sudo systemctl reboot", shell=True)
    messagebox.showinfo('Reboot NAS', 'Reboot NAS successfully!')
btn = Button(tab1, text="Reboot NAS", command=issue, height=1, width=12)
btn.grid(column=1, row=10, sticky='news')

def issue():
    subprocess.run("ssh [email protected] sudo systemctl poweroff", shell=True)
    messagebox.showinfo('Power Off NAS', 'Power Off NAS successfully!')
btn = Button(tab1, text="Power Off NAS", command=issue, height=1, width=12)
btn.grid(column=2, row=10, sticky='news')

text_area = scrolledtext.ScrolledText(tab1, width = 50 , height = 15, wrap="word")
text_area.grid(column=3, row=1, rowspan=12)

#Tab Computer
def issue():
    subprocess.run('sudo systemctl start pyload', shell=True)
    messagebox.showinfo('Start PyLoad', 'PyLoad Started successfully!')
btn = Button(tab2, text="Start PyLoad", command=issue, height=1, width=12)
btn.grid(column=1, row=1, sticky='news')

def issue():
    subprocess.run("sudo systemctl stop pyload", shell=True,)
    messagebox.showinfo('Stop PyLoad', 'Pyload Stopped successfully!')
btn = Button(tab2, text="Stop PyLoad", command=issue, height=1, width=12)
btn.grid(column=2, row=1, sticky='news')

text_area = scrolledtext.ScrolledText(tab2, width = 50 , height = 15, wrap="word")
text_area.grid(column=3, row=1, rowspan=12)

tab_control.pack(expand=1, fill='both')

#event loop
window.mainloop()
Reply
#4
Don't use line 12 until you want to stop text from going to the file.

The way you have it set, you redirect stdout, then immediately switch it back.
the sys.stdout = hold_stdout statement shouldn't be issued until you've captured all that you want to.

Also, don't need to issuefor each command unless you need to process what's being saved.

You can change the open command to be unbuffered by using (on line 13)
sys.stdout = open(savefile, 'w', buffering=0)

Then you should be able to open the savefile is i/o mode (r+) and read what's going on.
I haven't tried this, and not sure if it will lead to file pointer problems, but so long as you're
using a single thread, all should be OK.
Reply
#5
I have a fully functional windows terminal in python tkinter. It even supports full screen apps. You can ssh from inside the window to a Linux host and run full screen terminal apps like vi and htop. You can install via pip to test. It's called tkwinterm, here's the full repo https://github.com/scottpeterman/tkwinterm. It uses pywinpty, which is something you might want to look in to if you want to build your own terminal interfaces. You will get a lot more out of it than with subprocess, like color support for starters.
Reply
#6
(Feb-03-2024, 01:48 PM)speterman1987 Wrote: I have a fully functional windows terminal in python tkinter. It even supports full screen apps.
This looks interesting. Too bad you don't have a cross-platform terminal in tkinter. That would be very nice widget! In my collection of old codes, I have a pygtk console in my gists named umitconsole. It is a very old code which I copied two decades ago from a project named Umit. Needless to say that the code probably doesn't work any more but it may contain useful ideas in this direction.
« We can solve any problem by introducing an extra level of indirection »
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  Tkinter | entry output. Sap2ch 1 1,951 Sep-25-2021, 12:38 AM
Last Post: Yoriz
  How to show terminal output in GUI Rubberduck 2 8,538 May-29-2021, 09:01 AM
Last Post: Rubberduck
  [Tkinter] acceleration of data output in treeview tkinter Vladimir1984 4 4,097 Nov-21-2020, 03:43 PM
Last Post: Vladimir1984
  Displaying output in GUI ( Tkinter) Zouloutamtam 7 18,201 Sep-29-2020, 02:08 PM
Last Post: Zouloutamtam
  [Tkinter] Logs and terminal in Tkinter Prezess 1 3,123 Jul-26-2020, 09:49 PM
Last Post: Larz60+
  How to display results from terminal window onto tkinter. buttercup 0 3,603 Jul-21-2020, 04:41 AM
Last Post: buttercup
  How to print out the wisget structure in shell menator01 0 1,580 Apr-26-2020, 04:20 AM
Last Post: menator01
  [GTK] Virtual python shell with Vte.Pty.spawn_async() jiri 2 3,315 Oct-20-2019, 12:16 PM
Last Post: Axel_Erfurt
  Active tkinter text output during loop dvanommen 2 10,686 Oct-18-2019, 02:23 PM
Last Post: dvanommen
  sQlite3 output to tkinter treeview - how do I set / increase width of the output? dewijones67 5 6,576 Jan-23-2019, 08:45 AM
Last Post: Larz60+

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020