Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I create a small IDLE-like Python Shell in Tkinter?

I'm trying to make a thing controlled by a Python Shell GUI.

The only thing is, I don't know how to make that whole input/output thing. I just want to be able to type an input, execute the python command and give the output of the python command. I know that IDLE is made in Tkinter, so it uses the widgets?

It's literally just a "type input, show output" thing.

I've tried searching it up but it seems like most of the results are to do with the command line, which isn't what I'm looking for. The only other question that was exactly like mine wasn't what I had in mind, either. I also tried loking up the source code for IDLE but couldn't find what I was looking for.

I've found some answers that work for Linux but I'm on Windows 10...

I need the "shell" to be in Tkinter because on one side of the screen will be something else which is connected to the command outputs.

Does anyone know the widgets used to make a very simple Python shell?

like image 676
Eleeza the Other World Wizard Avatar asked Dec 03 '19 19:12

Eleeza the Other World Wizard


People also ask

Is Python IDLE made in Tkinter?

IDLE, Python's Integrated Development and Learning Environment, is written using Tkinter and is often distributed with Python. You can learn about features of Tkinter by playing around with menus and dialogs of IDLE. For instance, Options > Configure IDLE...

Is IDLE and Python shell same?

IDLE is the standard Python development environment. Its name is an acronym of "Integrated DeveLopment Environment". It works well on both Unix and Windows platforms. It has a Python shell window, which gives you access to the Python interactive mode.

How do I use IDLE in Python shell?

To execute a file in IDLE, simply press the F5 key on your keyboard. You can also select Run → Run Module from the menu bar. Either option will restart the Python interpreter and then run the code that you've written with a fresh interpreter.

How do you write Python code in IDLE?

Clicking on IDLE will open up the Python shell. You can either start writing your code here or hit control + N and open up a new file. Write your code in this file and save it. IDLE automatically saves all the files either with .


1 Answers

Simple Python Shell / Terminal / Command-Prompt


  • ********************* It's literally just a "type input, show output" thing. ************************

import os
from tkinter import *
from subprocess import *


class PythonShell:

    def __init__(self):
        self.master = Tk()

        self.mem_cache = open("idle.txt", "w+")
        self.body = None
        self.entry = None
        self.button = None
        self.entry_content = None

    @staticmethod
    def welcome_note():
        """
        To show welcome note on tkinter window
        :return:
        """
        Label(text="Welcome To My Python Program [Version 1.0]", font='Arial 12', background="#272626",
              foreground="white").pack()

        Label(text=">> Insert Python Commands <<", font='Arial 12', background="#272626",
              foreground="white").pack()

    def get_text(self):
        """
        This method will perform following operations;
        1- Get text from body
        2- Implies python compilation (treat text as command)
        3- Set Output in Output-Entry

        :return: get and set text in body of text box
        """
        content = self.body.get(1.0, "end-1c")
        out_put = self.run_commands(content)
        self.entry_content.set(out_put)

    def store_commands(self, command=None):

        try:
            self.mem_cache.write(command + ';')
            self.mem_cache.close()

        except Exception as e:
            print(e)

    def get_stored_commands(self):
        try:
            with open("idle.txt", "r") as self.mem_cache:
                self.mem_cache.seek(0)
                val = self.mem_cache.read()
                self.mem_cache.close()
                return val

        except Exception as e:
            print(e)

    @staticmethod
    def check_if_file_empty():
        size = os.stat("idle.txt").st_size

        if size != 0:
            return True
        else:
            return False

    def run_commands(self, command):
        """

        This method would return output of every command place in text box
        :param command: python command from text box
        :return: output of command
        """

        print("Running command: {}".format(command))
        value = None
        new_line_char = command.find('\n')
        semi_colons_char = command.find(';')
        double_quote = command.find('"')

        try:
            if new_line_char != -1:

                if semi_colons_char != -1 & double_quote == -1:

                    new_cmd = command.replace("\n", "")
                    cmd_value = '"' + new_cmd + '"'
                    self.store_commands(command)

                    value = check_output("python -c " + cmd_value, shell=True).decode()
                elif semi_colons_char == -1 & double_quote == -1:

                    new_cmd = command.replace("\n", ";")
                    cmd_value = '"' + new_cmd + '"'
                    self.store_commands(command)
                    value = check_output("python -c " + cmd_value, shell=True).decode()

                elif double_quote != -1:

                    cmd_1 = command.replace('"', "'")
                    new_cmd = cmd_1.replace('\n', ';')

                    cmd_value = '"' + new_cmd + '"'
                    self.store_commands(command)

                    value = check_output("python -c " + cmd_value, shell=True).decode()

                elif self.body.compare("end-1c", "==", "1.0"):
                    self.entry_content.set("the widget is empty")

            elif self.body.compare("end-1c", "==", "1.0"):
                value = "The widget is empty. Please Enter Something."

            else:
                variable_analyzer = command.find('=')
                file_size = PythonShell.check_if_file_empty()

                if file_size:
                    new_cmd = command.replace('"', "'")
                    cmd_value = '"' + new_cmd + '"'
                    stored_value = self.get_stored_commands()
                    cmd = stored_value + cmd_value
                    cmd.replace('"', '')

                    value = check_output("python -c " + cmd, shell=True).decode()
                elif variable_analyzer != -1:
                    new_cmd = command.replace('"', "'")
                    cmd_value = '"' + new_cmd + '"'
                    self.store_commands(cmd_value)

                    value = 'Waiting for input...'
                    pass
                else:
                    new_cmd = command.replace('"', "'")
                    cmd_value = '"' + new_cmd + '"'
                    value = check_output("python -c " + cmd_value, shell=True).decode()

        except Exception as ex:
            print('>>>', ex)
            self.entry_content.set('Invalid Command. Try again!!!')

        print('>>', value)
        # To Clear Text body After Button Click
        # self.body.delete('1.0', END)

        return value

    def start_terminal(self):
        """
        Initiate tkinter session to place and run commands
        :return:
        """
        self.master.propagate(0)
        self.master.geometry('750x350')
        self.master.title('Python IDLE')
        self.master.configure(background='#272626')

        terminal.welcome_note()

        self.body = Text(self.master, height='10', width='75', font='Consolas 12', background="#272626",
                         foreground="white",
                         insertbackground='white')
        # self.body.propagate(0)
        self.body.pack(expand=True)

        Label(text=">> Command Output <<", font='Arial 12', background="#272626",
              foreground="white").pack()

        self.entry_content = StringVar()
        self.entry = Entry(self.master, textvariable=self.entry_content, width=50, font='Consolas 16',
                           background="white",
                           foreground="black")
        self.entry.pack()
        # self.entry.propagate(0)

        self.button = Button(self.master, text="Run Command", command=self.get_text, background="white",
                             foreground="black",
                             font='Helvetica 12').pack()

        self.master.mainloop()


if __name__ == '__main__':
    terminal = PythonShell()
    terminal.start_terminal()

The above given python script has following hierarchy as given;

    |import ...      
    |class PythonShell:
        |def __init__(self):...

        @staticmethod
        |def welcome_note():...
        |def get_text(self):...
        |def store_commands(self, commmand):...
        |def get_stored_commands(self):...

        @staticmethod
        |def check_if_file_empty():
        |def run_commands(self, command):...
        |def start_terminal(self):...

    |if __name__ == '__main__':...

Workflow:

The basic workflow for the above code is given as follows;

  • def welcome_note():... Includes the Label that will display outside the text body.

  • def get_text(self):... Performs two operations; ** Get text from text body ** & ** Set Output in the Entry Box **.

  • def store_commands(self, command):... Use to store variable into file.

  • def get_stored_commands(self):... Get variable stored in file.

  • def check_if_file_empty():... Check Size of file.

  • def run_commands(self, command):... This method act as python compiler that take commands, do processing and yield output for the given command. To run commands, i would recommend to use subprocess-module because it provides more powerful facilities for spawning new processes and retrieving their results; To run window-commands using python includes various builtin libraries such as;

    1. os (in detail), 2. subprocess (in detail) etc.

    To checkout which is better to use, visit reference: subprocess- module is preferable than os-module.

  • def start_terminal(self):... This method simply involves the functionality to initiate tkinter session window and show basic layout for input and output window.

    You can further modify and optimize this code according to your requirement.


Workaroud:

This simple tkinter GUI based python shell perform simple functionality as windows-command-prompt. To run python commands directly in command-prompt without moving into python terminal, we do simple as;

python -c "print('Hey Eleeza!!!')"

Its result would be simple as;

Hey Eleeza!!!

Similarly, to run more than one lines directly at a time as given;

python -c "import platform;sys_info=platform.uname();print(sys_info)"

Its output would be as;

My System Info: uname_result(system='Windows', node='DESKTOP-J75UTG5', release='10', version='10.0.18362', machine='AMD64', processor='Intel64 Family 6 Model 142 Stepping 10, GenuineIntel')

So to use this tkinter python shell;

  • Either you can place command as;

    import platform
    value=platform.uname()
    print('Value:', value)
    
  • or like this way;

    import platform;value=platform.uname();
    print('Value:', value)
    
  • or simply inline command as

    import platform;value=platform.uname();print('Value:', value)
    

You will get the same result.

like image 124
Muhammad Usman Bashir Avatar answered Oct 21 '22 09:10

Muhammad Usman Bashir