Tkinter'de IDLE benzeri küçük bir Python Kabuğu nasıl oluşturabilirim?


9

Python Shell GUI tarafından kontrol edilen bir şey yapmaya çalışıyorum.

Tek şey, o bütün girdi / çıktı şeyi nasıl yapacağımı bilmiyorum. Sadece bir girdi yazmak, python komutunu yürütmek ve python komutunun çıktısını vermek istiyorum. IDLE Tkinter'da yapıldığını biliyorum, bu yüzden widget'ları kullanıyor?

Kelimenin tam anlamıyla sadece bir "tip girdi, çıktı göster" şey.

Ben aramaya çalıştım ama sonuçların çoğu komut satırı ile yapmak gibi görünüyor, ben aradığım bu değil. Benimki gibi olan tek soru da aklımdaki soru değildi. Ayrıca IDLE için kaynak kodunu loke etmeyi denedim ama aradığım şeyi bulamadım.

Linux için çalışan bazı cevaplar buldum ama Windows 10'dayım ...

Ekranın bir tarafında komut çıkışlarına bağlı başka bir şey olacak çünkü Tkinter olmak "kabuk" gerekir.

Herkes çok basit bir Python kabuğu yapmak için kullanılan widget'ları biliyor mu?



Bu soru silinmiş bir başkasının takipine benziyor, silinen sorunun bağlamı olmadan bana mantıklı gelmedi ... en azından şimdi bunun mümkün olduğunu biliyorum - ve ben değilim sadece bir şey yapmaya çalışıyor ... tekrar
Eleeza Karakter Sihirbazı

2
Idle python ile yazılır, tkinter kullanılarak ... kaynak kodunu okuyun .
Reblochon Masque

Yanıtlar:


6

Basit Python Kabuğu / Terminal / Komut İstemi


  • ********************* Kelimenin tam anlamıyla sadece " type input, show output" bir şey. ************************

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()

Yukarıda verilen python betiği aşağıdaki gibi hiyerarşiye sahiptir;

    |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__':...

İş Akışı:

Yukarıdaki kod için temel iş akışı aşağıdaki gibidir;

  • def welcome_note():... Metin gövdesinin dışında görüntülenecek Etiketi içerir.

  • def get_text(self):...İki işlem gerçekleştirir; ** Metin gövdesinden metin alın ** & ** Giriş Kutusunda Çıkışı Ayarla **.

  • def store_commands(self, command):... Değişkeni dosyaya kaydetmek için kullanın.

  • def get_stored_commands(self):... Değişkeni dosyada saklayın.

  • def check_if_file_empty():... Dosyanın boyutunu kontrol edin.

  • def run_commands(self, command):...Bu yöntem , verilen komut için komut alan, işleme yapan ve çıktı veren python derleyicisi olarak işlev görür . Komutları çalıştırmak için, subprocess-moduleyeni süreçleri ortaya çıkarmak ve sonuçlarını almak için daha güçlü tesisler sağladığı için kullanmanızı tavsiye ederim ; Python kullanarak pencere komutlarını çalıştırmak için ;

    1. işletim sistemi ( ayrıntılı ), 2. alt işlem ( ayrıntılı ) vb.

    Hangisinin daha iyi kullanıldığını kontrol etmek için referansı ziyaret edin: alt işlem modülü os modülünden daha fazla tercih edilir .

  • def start_terminal(self):...Bu yöntem, tkinteroturum penceresini başlatma ve giriş ve çıkış penceresi için temel düzeni gösterme işlevini içerir .

    İhtiyacınıza göre bu kodu daha fazla değiştirebilir ve optimize edebilirsiniz.


Workaroud:

Bu basit tkinter GUI based python shell, windows-komut istemi olarak basit işlevsellik gerçekleştirir. Python komutlarını directlypython terminaline geçmeden komut isteminde çalıştırmak için ;

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

Sonuç olarak;

Hey Eleeza!!!

Benzer şekilde, verilen şekilde bir seferde birden fazla satırı doğrudan çalıştırmak için;

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

Çıktısı;

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')

Bunu kullanmak için tkinter python shell;

  • Komut olarak;

    import platform
    value=platform.uname()
    print('Value:', value)
  • ya da bu şekilde;

    import platform;value=platform.uname();
    print('Value:', value)
  • veya basitçe satır içi komut

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

Aynı sonucu alacaksınız.


1
Bu giriş / çıkış mükemmel, çok teşekkür ederim! Tek bir şey olsa da, bir değişken atarsam, komutu çalıştırır ve daha sonra değişkeni temizleyip yazdırmaya çalışırsam, bunu yapmaz, bu yüzden gerçek hayatta python'da çalıştırmak için komutu nasıl alacağım (eğer değilse) yapıyor)?
Eleeza Karakter Sihirbazı

2
@Eleeza, her şeyden önce sorunuz bu tür bir gereksinimi içermiyordu. Çok basit inputolduğu için output kabuk. Temel gibi davranır python kernel. Yalnızca metin gövdesine yerleştirilmiş olarak çalışır . Değişken geçmişini tutmak için herhangi bir arabellek veya bellek önbelleği ayarlamadım . Önce bu IDLE'deki bu gereksinimi kontrol edeyim!
Muhammed Usman

1
Yapacağım şey, tüm dünyanın ana koda programlandığı ve terminalin onu keşfetmek ve onunla etkileşim kurmak için kullanıldığı bir oyundu. Ben sadece çıktı göstermeden önce kod yürütme bir durum olacağını düşündüm ama bunu kontrol etmek zorunda kalacağım.
Eleeza Karakter Sihirbazı

2
Ayrıntılı olarak açıklanmıştır: İnsanların, mekanların vb. Hepsinin Python'daki nesneler olduğu ana oyun programında bir tür "dünya" yapıyorum. Oyuncu, python komutlarını kullanarak GUI terminali aracılığıyla dünyayı dolaşmak zorunda, bu Python'u keşfederek öğrenmekle ilgili bir oyundur. Kod aslında gerçek hayatta değiştirilir (ancak daha sonra sıfırlanır).
Eleeza Karakter Sihirbazı

8
@Eleeza, İşte size tam bir parça verebilir en iyi github deposu ; Referansı ziyaret edin: github.com/codecombat/codecombat . Bunlara da bakmak zorunda olduğunuz diğer referanslar; github.com/replit/play , github.com/jatinmandav/Gaming-in-Python , github.com/PacktPublishing/-Learn-Python-Programming-with-Games , github.com/… , github.com/pyland/pyland , İşte başka bir referans da github.com/CharlesPikachu/Games
Muhammed Usman

4

Bu, temel exec()olarak python deyimlerini subprocess.Popen()yürütmek ve harici komutu yürütmek için kullanılan basit bir kabuktur :

import tkinter as tk
import sys, io
import subprocess as subp
from contextlib import redirect_stdout

class Shell(tk.Text):
  def __init__(self, parent, **kwargs):
    tk.Text.__init__(self, parent, **kwargs)
    self.bind('<Key>', self.on_key) # setup handler to process pressed keys
    self.cmd = None        # hold the last command issued
    self.show_prompt()

  # to append given text at the end of Text box
  def insert_text(self, txt='', end='\n'):
    self.insert(tk.END, txt+end)
    self.see(tk.END) # make sure it is visible

  def show_prompt(self):
    self.insert_text('>> ', end='')
    self.mark_set(tk.INSERT, tk.END) # make sure the input cursor is at the end
    self.cursor = self.index(tk.INSERT) # save the input position

  # handler to process keyboard input
  def on_key(self, event):
    #print(event)
    if event.keysym == 'Up':
      if self.cmd:
        # show the last command
        self.delete(self.cursor, tk.END)
        self.insert(self.cursor, self.cmd)
      return "break" # disable the default handling of up key
    if event.keysym == 'Down':
      return "break" # disable the default handling of down key
    if event.keysym in ('Left', 'BackSpace'):
      current = self.index(tk.INSERT) # get the current position of the input cursor
      if self.compare(current, '==', self.cursor):
        # if input cursor is at the beginning of input (after the prompt), do nothing
        return "break"
    if event.keysym == 'Return':
      # extract the command input
      cmd = self.get(self.cursor, tk.END).strip()
      self.insert_text() # advance to next line
      if cmd.startswith('`'):
        # it is an external command
        self.system(cmd)
      else:
        # it is python statement
        self.execute(cmd)
      self.show_prompt()
      return "break" # disable the default handling of Enter key
    if event.keysym == 'Escape':
      self.master.destroy() # quit the shell

  # function to handle python statement input
  def execute(self, cmd):
    self.cmd = cmd  # save the command
    # use redirect_stdout() to capture the output of exec() to a string
    f = io.StringIO()
    with redirect_stdout(f):
      try:
        exec(self.cmd, globals())
      except Exception as e:
        print(e)
    # then append the output of exec() in the Text box
    self.insert_text(f.getvalue(), end='')

  # function to handle external command input
  def system(self, cmd):
    self.cmd = cmd  # save the command
    try:
      # extract the actual command
      cmd = cmd[cmd.index('`')+1:cmd.rindex('`')]
      proc = subp.Popen(cmd, stdout=subp.PIPE, stderr=subp.PIPE, text=True)
      stdout, stderr = proc.communicate(5) # get the command output
      # append the command output to Text box
      self.insert_text(stdout)
    except Exception as e:
      self.insert_text(str(e))

root = tk.Tk()
root.title('Simple Python Shell')

shell = Shell(root, width=100, height=50, font=('Consolas', 10))
shell.pack(fill=tk.BOTH, expand=1)
shell.focus_set()

root.mainloop()

Sadece normal python deyimini girin:

>> x = 1
>> print(x)
1

Veya bir kabuk komutu girin:

>> `cmd /c date /t`
2019-12-09

UpSon komutu çağırmak için tuşunu da kullanabilirsiniz .

Kullanıcı girişi gerektiren bir sistem komutu yürütürseniz, kabuğun 5 saniye boyunca donacağını unutmayın (zaman aşımı süresi kullanılır communicate()).

İhtiyacınıza göre on_key()işlevi değiştirebilirsiniz .

Lütfen kullanmanın exec()iyi bir uygulama olmadığını da unutmayın.


Kodu açıklayabilir misiniz, lütfen? Bunların hepsine biraz yeni
başlıyorum

1
Koduma yorum ekledim, umarım yardımcı olur.
acw1668

4

code.InteractiveConsoleBir proje için komutları yürütmek için python kabuğu uygulamıştım . Aşağıda basitleştirilmiş bir sürüm, yine de oldukça uzun olsa da, python konsolunda olduğu gibi davranması için özel anahtarlar (Return, Tab ... gibi) için bağlamalar yazmıştım. Jedi ile otomatik tamamlama ve pygments ile sözdizimi vurgulama gibi daha fazla özellik eklemek mümkündür.

Ana fikir komutları yürütmek için push()yöntemini kullanmaktır code.InteractiveConsole. Bu yöntem True, örneğin def test(x):, kısmi bir komutsa döndürür ve bir bilgi ...istemi eklemek için bu geri bildirimi kullanırım , aksi takdirde çıktı görüntülenir ve yeni bir bilgi >>>istemi görüntülenir. Çıktıyı kullanarak yakalarım contextlib.redirect_stdout.

Ayrıca, kullanıcının önceden yürütülen komutların içine metin eklemesini engellediğim için işaretleri içeren ve dizinleri karşılaştıran bir sürü kod var. Fikir, aktif istemin başlangıcının nerede olduğunu söyleyen bir işaret 'girişi' oluşturduğum ve kullanıcının aktif istemin üzerine self.compare('insert', '<', 'input')ne zaman metin eklemeye çalıştığını bilebilirim.

import tkinter as tk
import sys
import re
from code import InteractiveConsole
from contextlib import redirect_stderr, redirect_stdout
from io import StringIO


class History(list):
    def __getitem__(self, index):
        try:
            return list.__getitem__(self, index)
        except IndexError:
            return


class TextConsole(tk.Text):
    def __init__(self, master, **kw):
        kw.setdefault('width', 50)
        kw.setdefault('wrap', 'word')
        kw.setdefault('prompt1', '>>> ')
        kw.setdefault('prompt2', '... ')
        banner = kw.pop('banner', 'Python %s\n' % sys.version)
        self._prompt1 = kw.pop('prompt1')
        self._prompt2 = kw.pop('prompt2')
        tk.Text.__init__(self, master, **kw)
        # --- history
        self.history = History()
        self._hist_item = 0
        self._hist_match = ''

        # --- initialization
        self._console = InteractiveConsole() # python console to execute commands
        self.insert('end', banner, 'banner')
        self.prompt()
        self.mark_set('input', 'insert')
        self.mark_gravity('input', 'left')

        # --- bindings
        self.bind('<Control-Return>', self.on_ctrl_return)
        self.bind('<Shift-Return>', self.on_shift_return)
        self.bind('<KeyPress>', self.on_key_press)
        self.bind('<KeyRelease>', self.on_key_release)
        self.bind('<Tab>', self.on_tab)
        self.bind('<Down>', self.on_down)
        self.bind('<Up>', self.on_up)
        self.bind('<Return>', self.on_return)
        self.bind('<BackSpace>', self.on_backspace)
        self.bind('<Control-c>', self.on_ctrl_c)
        self.bind('<<Paste>>', self.on_paste)

    def on_ctrl_c(self, event):
        """Copy selected code, removing prompts first"""
        sel = self.tag_ranges('sel')
        if sel:
            txt = self.get('sel.first', 'sel.last').splitlines()
            lines = []
            for i, line in enumerate(txt):
                if line.startswith(self._prompt1):
                    lines.append(line[len(self._prompt1):])
                elif line.startswith(self._prompt2):
                    lines.append(line[len(self._prompt2):])
                else:
                    lines.append(line)
            self.clipboard_clear()
            self.clipboard_append('\n'.join(lines))
        return 'break'

    def on_paste(self, event):
        """Paste commands"""
        if self.compare('insert', '<', 'input'):
            return "break"
        sel = self.tag_ranges('sel')
        if sel:
            self.delete('sel.first', 'sel.last')
        txt = self.clipboard_get()
        self.insert("insert", txt)
        self.insert_cmd(self.get("input", "end"))
        return 'break'

    def prompt(self, result=False):
        """Insert a prompt"""
        if result:
            self.insert('end', self._prompt2, 'prompt')
        else:
            self.insert('end', self._prompt1, 'prompt')
        self.mark_set('input', 'end-1c')

    def on_key_press(self, event):
        """Prevent text insertion in command history"""
        if self.compare('insert', '<', 'input') and event.keysym not in ['Left', 'Right']:
            self._hist_item = len(self.history)
            self.mark_set('insert', 'input lineend')
            if not event.char.isalnum():
                return 'break'

    def on_key_release(self, event):
        """Reset history scrolling"""
        if self.compare('insert', '<', 'input') and event.keysym not in ['Left', 'Right']:
            self._hist_item = len(self.history)
            return 'break'

    def on_up(self, event):
        """Handle up arrow key press"""
        if self.compare('insert', '<', 'input'):
            self.mark_set('insert', 'end')
            return 'break'
        elif self.index('input linestart') == self.index('insert linestart'):
            # navigate history
            line = self.get('input', 'insert')
            self._hist_match = line
            hist_item = self._hist_item
            self._hist_item -= 1
            item = self.history[self._hist_item]
            while self._hist_item >= 0 and not item.startswith(line):
                self._hist_item -= 1
                item = self.history[self._hist_item]
            if self._hist_item >= 0:
                index = self.index('insert')
                self.insert_cmd(item)
                self.mark_set('insert', index)
            else:
                self._hist_item = hist_item
            return 'break'

    def on_down(self, event):
        """Handle down arrow key press"""
        if self.compare('insert', '<', 'input'):
            self.mark_set('insert', 'end')
            return 'break'
        elif self.compare('insert lineend', '==', 'end-1c'):
            # navigate history
            line = self._hist_match
            self._hist_item += 1
            item = self.history[self._hist_item]
            while item is not None and not item.startswith(line):
                self._hist_item += 1
                item = self.history[self._hist_item]
            if item is not None:
                self.insert_cmd(item)
                self.mark_set('insert', 'input+%ic' % len(self._hist_match))
            else:
                self._hist_item = len(self.history)
                self.delete('input', 'end')
                self.insert('insert', line)
            return 'break'

    def on_tab(self, event):
        """Handle tab key press"""
        if self.compare('insert', '<', 'input'):
            self.mark_set('insert', 'input lineend')
            return "break"
        # indent code
        sel = self.tag_ranges('sel')
        if sel:
            start = str(self.index('sel.first'))
            end = str(self.index('sel.last'))
            start_line = int(start.split('.')[0])
            end_line = int(end.split('.')[0]) + 1
            for line in range(start_line, end_line):
                self.insert('%i.0' % line, '    ')
        else:
            txt = self.get('insert-1c')
            if not txt.isalnum() and txt != '.':
                self.insert('insert', '    ')
        return "break"

    def on_shift_return(self, event):
        """Handle Shift+Return key press"""
        if self.compare('insert', '<', 'input'):
            self.mark_set('insert', 'input lineend')
            return 'break'
        else: # execute commands
            self.mark_set('insert', 'end')
            self.insert('insert', '\n')
            self.insert('insert', self._prompt2, 'prompt')
            self.eval_current(True)

    def on_return(self, event=None):
        """Handle Return key press"""
        if self.compare('insert', '<', 'input'):
            self.mark_set('insert', 'input lineend')
            return 'break'
        else:
            self.eval_current(True)
            self.see('end')
        return 'break'

    def on_ctrl_return(self, event=None):
        """Handle Ctrl+Return key press"""
        self.insert('insert', '\n' + self._prompt2, 'prompt')
        return 'break'

    def on_backspace(self, event):
        """Handle delete key press"""
        if self.compare('insert', '<=', 'input'):
            self.mark_set('insert', 'input lineend')
            return 'break'
        sel = self.tag_ranges('sel')
        if sel:
            self.delete('sel.first', 'sel.last')
        else:
            linestart = self.get('insert linestart', 'insert')
            if re.search(r'    $', linestart):
                self.delete('insert-4c', 'insert')
            else:
                self.delete('insert-1c')
        return 'break'

    def insert_cmd(self, cmd):
        """Insert lines of code, adding prompts"""
        input_index = self.index('input')
        self.delete('input', 'end')
        lines = cmd.splitlines()
        if lines:
            indent = len(re.search(r'^( )*', lines[0]).group())
            self.insert('insert', lines[0][indent:])
            for line in lines[1:]:
                line = line[indent:]
                self.insert('insert', '\n')
                self.prompt(True)
                self.insert('insert', line)
                self.mark_set('input', input_index)
        self.see('end')

    def eval_current(self, auto_indent=False):
        """Evaluate code"""
        index = self.index('input')
        lines = self.get('input', 'insert lineend').splitlines() # commands to execute
        self.mark_set('insert', 'insert lineend')
        if lines:  # there is code to execute
            # remove prompts
            lines = [lines[0].rstrip()] + [line[len(self._prompt2):].rstrip() for line in lines[1:]]
            for i, l in enumerate(lines):
                if l.endswith('?'):
                    lines[i] = 'help(%s)' % l[:-1]
            cmds = '\n'.join(lines)
            self.insert('insert', '\n')
            out = StringIO()  # command output
            err = StringIO()  # command error traceback
            with redirect_stderr(err):     # redirect error traceback to err
                with redirect_stdout(out): # redirect command output
                    # execute commands in interactive console
                    res = self._console.push(cmds)
                    # if res is True, this is a partial command, e.g. 'def test():' and we need to wait for the rest of the code
            errors = err.getvalue()
            if errors:  # there were errors during the execution
                self.insert('end', errors)  # display the traceback
                self.mark_set('input', 'end')
                self.see('end')
                self.prompt() # insert new prompt
            else:
                output = out.getvalue()  # get output
                if output:
                    self.insert('end', output, 'output')
                self.mark_set('input', 'end')
                self.see('end')
                if not res and self.compare('insert linestart', '>', 'insert'):
                    self.insert('insert', '\n')
                self.prompt(res)
                if auto_indent and lines:
                    # insert indentation similar to previous lines
                    indent = re.search(r'^( )*', lines[-1]).group()
                    line = lines[-1].strip()
                    if line and line[-1] == ':':
                        indent = indent + '    '
                    self.insert('insert', indent)
                self.see('end')
                if res:
                    self.mark_set('input', index)
                    self._console.resetbuffer()  # clear buffer since the whole command will be retrieved from the text widget
                elif lines:
                    self.history.append(lines)  # add commands to history
                    self._hist_item = len(self.history)
            out.close()
            err.close()
        else:
            self.insert('insert', '\n')
            self.prompt()


if __name__ == '__main__':
    root = tk.Tk()
    console = TextConsole(root)
    console.pack(fill='both', expand=True)
    root.mainloop()

Dürüst olmak gerekirse, bu kabul edilen cevap olmalıdır.
TheMaker
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.