Skip to main content
 首页 » 编程设计

wxPython:如何创建 bash shell 窗口

2025年05月04日11Leo_wl

我想使用 wxPython 创建一个像 bash shell 一样的弹出窗口。我不需要终端仿真器,不需要作业控制,我只需要基于 bash 进程的 REPL(读取、评估、打印循环)。

有没有一种简单的方法可以用 wxPython 做到这一点?我知道我作为 tcl/tk 程序员时的基本概念,但我的 wxPython fu 很弱,如果不需要的话,我不想重新发明轮子。我已经阅读了一些有关 py.shell 的内容。 Shell,但看起来它创建了一个 python shell,我想要一个运行 bash 命令。

请您参考如下方法:

好的,这是另一种尝试,它也在一个单独的线程中读取所有输出和错误,并通过队列进行通信。 我知道它并不完美(例如,带有延迟输出的命令将不起作用,并且输出将进入下一个命令,例如 tryr sleep 1; date)并复制整个 bash 不是微不足道的,但对于我测试的几个命令,它似乎工作正常

关于wx.py.shell的API,我只是实现了Shell类为Interpreter调用的那些方法,如果你通过Shell的源代码你就会明白。 基本上

  • push 是将用户输入的命令发送给解释器的地方
  • getAutoCompleteKeys 返回 key 哪个用户可以使用 自动完成命令,例如制表键
  • getAutoCompleteList 返回列表 命令匹配给定文本

  • getCallTip "显示参数规范和 弹出窗口中的文档字符串。因此对于 bash 我们可能会显示手册页:)

这里是源码

import threading 
import Queue 
import time 
 
import wx 
import wx.py 
from subprocess import Popen, PIPE 
 
class BashProcessThread(threading.Thread): 
    def __init__(self, readlineFunc): 
        threading.Thread.__init__(self) 
 
        self.readlineFunc = readlineFunc 
        self.outputQueue = Queue.Queue() 
        self.setDaemon(True) 
 
    def run(self): 
        while True: 
            line = self.readlineFunc() 
            self.outputQueue.put(line) 
 
    def getOutput(self): 
        """ called from other thread """ 
        lines = [] 
        while True: 
            try: 
                line = self.outputQueue.get_nowait() 
                lines.append(line) 
            except Queue.Empty: 
                break 
        return ''.join(lines) 
 
class MyInterpretor(object): 
    def __init__(self, locals, rawin, stdin, stdout, stderr): 
        self.introText = "Welcome to stackoverflow bash shell" 
        self.locals = locals 
        self.revision = 1.0 
        self.rawin = rawin 
        self.stdin = stdin 
        self.stdout = stdout 
        self.stderr = stderr 
 
        self.more = False 
 
        # bash process 
        self.bp = Popen('bash', shell=False, stdout=PIPE, stdin=PIPE, stderr=PIPE) 
 
        # start output grab thread 
        self.outputThread = BashProcessThread(self.bp.stdout.readline) 
        self.outputThread.start() 
 
        # start err grab thread 
        self.errorThread = BashProcessThread(self.bp.stderr.readline) 
        self.errorThread.start() 
 
    def getAutoCompleteKeys(self): 
        return [ord('\t')] 
 
    def getAutoCompleteList(self, *args, **kwargs): 
        return [] 
 
    def getCallTip(self, command): 
        return "" 
 
    def push(self, command): 
        command = command.strip() 
        if not command: return 
 
        self.bp.stdin.write(command+"\n") 
        # wait a bit 
        time.sleep(.1) 
 
        # print output 
        self.stdout.write(self.outputThread.getOutput()) 
 
        # print error 
        self.stderr.write(self.errorThread.getOutput()) 
 
app = wx.PySimpleApp() 
frame = wx.py.shell.ShellFrame(InterpClass=MyInterpretor) 
frame.Show() 
app.SetTopWindow(frame) 
app.MainLoop()