将具有连续标准输出的Paramiko嵌入到tkinter GUI中(在tkinter中创建SSH命令行输出)

时间:2018-11-07 19:05:51

标签: python python-2.7 tkinter paramiko

我正在尝试创建一个tkinter GUI,该GUI实际上将用作到远程linux计算机的SSH连接。 GUI必须在Windows操作系统上可以运行。 GUI有几个按钮,允许用户启动和停止linux计算机上的程序,但是我在从此远程程序向tkinter打印连续输出时遇到问题。我本质上希望在tkinter GUI中有一个嵌入式窗口,该窗口显示远程桌面的命令行输出。

在下面的代码中,我成功调用了我的GUI类并构建了tkinter GUI。使用paramiko,我可以成功建立SSH连接,但是问题是当我按下“启动脚本”时。启动脚本通过SSH连接成功启动了该程序,但是我无法在GUI上打印连续的输出(要测试这一点,main_script.py是一个基本程序,每3秒只会输出一个递增的数字)。我相信问题是我拖延了tkinter主循环,但是我不知道如何解决这个问题。延迟后,我可以使用tkinter.after命令更新窗口,但是由于我读取stdout的方式,我的脚本仍然停滞。有没有更好的方法来读取stdout?我是否需要调用子进程或使用多线程(如果是这样,当main_window打开时我想建立SSH连接时该怎么做)。还是我错过了一种简单得多的方法,该方法实际上具有带有几个GUI按钮的远程桌面命令行输出?感谢您的帮助。

import paramiko
import tkinter as tk


class main_window():
    def __init__(self, root2, ip, user, pword):
        self.root2 = root2

        # Connection Label
        conn_label = tk.Label(root2, text=str('CONNECTED TO: ' + user + '    ' + 'ON: ' + ip))
        conn_label.grid(row=0, columnspan=6, sticky=tk.W)

        # Frequency Entery
        freq_label = tk.Label(root2, text='Tag Frequency:')
        freq_entry = tk.Entry(root2)
        self.freq_enter_button = tk.Button(root2, text='Enter')
        freq_label.grid(row=1, column=1, sticky=tk.E, padx=(5, 0))
        freq_entry.grid(row=1, column=2, sticky=tk.W)
        self.freq_enter_button.grid(row=1, column=3, padx=5)

        # Scroll Bar and Command Line Ouput
        self.scrollbar = tk.Scrollbar(root2)
        self.scrollbar.grid(row=3, column=5, rowspan=1, sticky=tk.N+tk.S)

        self.mylist = tk.Listbox(root2, yscrollcommand=self.scrollbar.set)
        self.mylist.grid(row=3, column=0, columnspan=5, sticky=tk.W+tk.E+tk.N+tk.S)

        # SSH Connection
        self.ssh = paramiko.SSHClient()
        self.ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
        self.ssh.connect(ip, port=22, username=user, password=pword)
        # stdin, stdout, stderr = ssh.exec_command('ls')
        # for line in stdout:
        #     mylist.insert(tk.END, str('... ' + line.strip('\n')))
        # ssh.close()

        # Start Script Button
        self.script_btn = tk.Button(root2, text="Start Script", command=self.toggle)
        self.script_btn.grid(row=2, column=1, columnspan=3, sticky=tk.W+tk.E, padx=(10, 8), pady=2)

        # Customize Grid Expansion
        root2.columnconfigure(0, weight=1)
        root2.columnconfigure(4, weight=1)
        root2.rowconfigure(3, weight=1)

        # Visual Touches
        root2.title("Terminal Connection")
        root2.wm_iconbitmap('logo_blue.ico')

    def toggle(self):
        def_color = self.freq_enter_button.cget('bg')
        if self.script_btn.config('text')[-1] == 'Start Script':
            stdin, self.stdout, stderr = self.ssh.exec_command('python main_script.py', get_pty=True)
            self.mylist.insert(tk.END, str('Starting Script\n'))
            self.script_btn.config(text='End Script', bg='red')
            self.update_window()
        else:
            stdin, self.stdout, stderr = self.ssh.exec_command(chr(3))
            self.mylist.insert(tk.END, str('Ending Script\n'))
            self.script_btn.config(text='Start Script', bg=def_color)

    def update_window(self):
        for line in iter(lambda: self.stdout.readline(), ""):
            self.mylist.insert(tk.END, str(line))
            self.scrollbar.config(command=self.mylist.yview)
        # self.root2.after(1000, self.update_window)


def main():
    root = tk.Tk()
    IP = '*********'
    user = '*******'
    pswd = '*******'
    runGUI = main_window(root, IP, user, pswd)
    root.title("Connect to Drone")
    root.wm_iconbitmap('logo_blue.ico')
    root.mainloop()


if __name__ == "__main__":
    main()

0 个答案:

没有答案