0

我正在尝试实现一个 tkinter 按钮,它应该在远程服务器中“tail -f”一些日志文件。它还应该在本地停止该进程并在第二次单击时终止远程尾进程。我通过不成功使用 tkinter 进行了尝试。当按下 ctrl c 时它停止。

单击tail(button3)按钮时,它会挂起并等待作业完成。在那之前它不接受任何新事件。我知道 tkinter 是单线程的,并且相信这是导致问题的原因。代码如下,感谢任何帮助。

from Tkinter import *
from re import *
import paramiko
import time
import select


class MyApp:
    def __init__(self, parent):
                self.myParent = parent   
                self.myContainer1 = Frame(parent,width=500,height=500)
                self.myContainer1.pack()
   #------------------ LABEL  #1 for MAC ------------------------------------               
        #mac label field
                self.label = Label (self.myContainer1, text='enter MAC').pack(side=TOP,padx=10,pady=10)
   #------------------ ENTRY FIELD  #1 for MAC ------------------------------------    
        #mac entry field
                mac_var=StringVar()
                self.entry = Entry(self.myContainer1,textvariable= mac_var ,width=10)
                self.entry.pack(side=TOP,padx=100,pady=10)
                mac_var.set("XXXXX")
                s=mac_var.get()




   #------------------ LABEL  #2 for MAC OWNER ------------------------------------                
        #name label field
                self.label = Label (self.myContainer1, text='enter MAC owner').pack(side=TOP,padx=10,pady=10)
   #------------------ ENTRY  #2 for MAC OWNER ------------------------------------     
        #name entry field
                name_var=StringVar()
                self.entry = Entry(self.myContainer1,textvariable= name_var ,width=25)
                self.entry.pack(side=TOP,padx=100,pady=10)
                name_var.set("name surname")
                s=name_var.get()




         #------------------ BUTTON #3 ------------------------------------      

        # event binding
                self.button3 = Button(self.myContainer1)
                self.button3.bind("<Button-1>", self.button3Click)
                self.button3.configure(text="tail", background="purple")
                self.button3.pack(side=LEFT)





    def button3Click(self, event):  
        if self.button3["background"] == "purple":
            self.button3.configure(text="Cancel Tail", background="yellow")
            self.tail_flag=True
            print "tail_flag is" , self.tail_flag
            self.taillogg()
        else:
            self.button3.configure(text="Tail", background="purple")
            self.canceltaillogg()
            #root.destroy()

    def canceltaillogg(self):
        self.tail_flag=False
        print "tail_flag is" , self.tail_flag

    def taillogg(self):
        server, port, username, password = ('myserver', 22, 'root', 'passw')
        paramiko.util.log_to_file("C:\\log_transport_paramiko.txt")
        nbytes = 100
        trans = paramiko.Transport((server, port))
        trans.connect(username = username, password = password)
        trans.set_keepalive(1) # when ssh dies (with Ctrl C) processes spawned by that ssh connections will die, too ( in one sec)
        sess = trans.open_channel("session")
        #Once the channel is established, we can execute only one command.
        #To execute another command, we need to create another channel
        sess.exec_command('tail -f /usr/local/var/log/radius/radius.log')
        timeout = 10
        timestart       =time.time()
        while True:
           try:
               rl, wl, xl = select.select([sess],[],[],0.0)
               if len(rl) > 0:   #stdout
                   print sess.recv(1024)
                   if  time.time()-timestart > timeout or self.tail_flag==False :
                        print "timeout 30 sec"
                        trans.close()
                        sess.close()
                        break
           except KeyboardInterrupt :
               print("Caught Control-C")
               trans.close()
               sess.close()
               break


           """if self.tail_flag==False:
               break"""



print ("\n")*100 # clear the screen
print "Starting program"                               
root = Tk()
root.title('MAC REGISTRATION APPLET')
myapp = MyApp(root)
print ("Ready to start executing the event loop.")
root.mainloop()
print ("Finished       executing the event loop.")
4

1 回答 1

1

试试这个 - 看看它是否给你你想要的行为。

self.button3.bind("<Button-1>", lambda:self.root.after(0, self.button3Click)

此外,这是不相关的,但您不必在按钮上调用“绑定” - 它有一个内置的回调属性,称为command

self.button3 = Button(self.myContainer1, command=lambda:self.root.after(0, self.button3Click))
# self.button3.bind("<Button-1>", self.button3Click)  (don't need this)

然后您需要event从函数中删除参数button3Click,因为按钮回调不接收任何参数。

于 2013-08-15T16:45:33.957 回答