2017-11-17 2 views
0

게시하기 전에 스택에 대한 제안 사항 중 몇 가지를 검색하여 적용했습니다. 아무도 일한 적이 없지만 아래 코드는 내가 일하는 가장 가까운 곳입니다.python 2.7에서 tkinter 프로젝트의 자체 업데이트가 영원히 반복됩니까?

내가 달성하고자하는 것은 여러 서버의 CPU, 프로세스 (현재 명령은 ls 임) 및 CRON 상태를 모니터하는 작은 GUI를 빌드하는 것입니다. 응용 프로그램이 자동으로 업데이트되는 기능을 제외한 모든 기능이 정상적으로 작동합니다. 이미 업데이트 버튼이 있으며 버튼을 매분마다 연결하는 기능을 refresh() 호출 할 수 있기를 원합니다.

필자는 tkinter를 처음 사용하고 프로그램에 작성한 다른 사례에 대해 약간의 의문을 가지고 있습니다. 놀라는 것이 있으시면 언제든지 말씀해주십시오.

현재 오류는 발생하지 않지만 계획된 지연없이 프로그램이 영원히 반복됩니다.

미리 감사드립니다.

#!/usr/bin/python 
import ttk, os, subprocess, datetime 
import ConfigParser 
from Tkinter import * 

config = ConfigParser.ConfigParser() 
config.read("p_watch.ini") 



def main(): 
    root = Tk() 
    root.title('Processor Watch') 
    root.geometry('800x480') 
    app = ProcessorWatch(root) 
    root.mainloop() 
    root.destroy() 



def ConfigSectionMap(section): 
    config_dict = {} 
    options = config.options(section) 
    for option in options: 
     try: 
      config_dict[option] = config.get(section, option) 
      if config_dict[option] == -1: 
       DebugPrint("skip: %s" % option) 
     except: 
      print("exception on %s!" % option) 
      config_dict[option] = None 
    return config_dict 



class ProcessorWatch: 

    def __init__(self, master): 

     ### create tabs for different machines 
     notebook = ttk.Notebook(master) 
     notebook.pack(side='top', fill=BOTH, expand=True) 
     frame1 = ttk.Frame(notebook) 
     frame1.pack(fill=BOTH, expand=True) 
     frame2 = ttk.Frame(notebook) 
     frame2.pack(fill=BOTH, expand=True) 
     frame3 = ttk.Frame(notebook) 
     frame3.pack(fill=BOTH, expand=True) 
     notebook.add(frame1, text='Processor1') 
     notebook.add(frame2, text='Processor2') 
     notebook.add(frame3, text='Processor3') 
     notebook.grid(sticky = 'NSEW') 

     frame1_creds = ConfigSectionMap('processor 1') 
     frame2_creds = ConfigSectionMap('processor 2') 
     frame3_creds = ConfigSectionMap('processor 3') 

     frame1.host_string = frame1_creds['user'] + '@' + frame1_creds['host'] 
     frame1.index  = 0 
     frame2.host_string = frame2_creds['user'] + '@' + frame1_creds['host'] 
     frame2.index  = 1 
     frame3.host_string = frame3_creds['user'] + '@' + frame1_creds['host'] 
     frame3.index  = 2 
     frames = [frame1,frame2,frame3] 

     self.cron_button = {} 
     self.spinbox = {} 
     self.refresh_num = {} 
     self.cpu_usage = {} 
     self.cpu_label = {} 
     self.usage_label = {} 
     self.quit_button = {} 
     self.refresh_button = {} 


     for frame in frames: 

      master.grid_columnconfigure(0, weight=1) 
      master.grid_rowconfigure(0, weight=1) 

      process_count = 0 

      ### execute terminal commands 
      self.cpu_usage[frame.index] = os.popen(
       "ssh -t " + frame.host_string + " grep 'cpu ' /proc/stat | awk '{usage=($2+$4)*100/($2+$4+$5)} END {print usage \"%\"}'" 
       ).read() 
      grep_results = os.popen("ls") 
      cron_activity = os.popen("ssh -t " + frame.host_string + " \'service cron status | grep Active\'").read() 

      ### determine and display CRON activity 
      if 'inactive (dead)' in cron_activity: 
       self.cron_button[frame.index] = Button(frame, text='CRON (inactive)',fg='white',bg='red', command= lambda f=frame: self.start_cron(master,f)) 
       self.cron_button[frame.index].grid(padx=20, ipady=15, pady=3,row=0, column=0, sticky='EW') 
      else : 
       self.cron_button[frame.index] = Button(frame, text='CRON (active)',fg='white',bg='green', command= lambda f=frame: self.stop_cron(master,f)) 
       self.cron_button[frame.index].grid(padx=20, ipady=15, pady=3,row=0, column=0, sticky='EW') 

      ### config and display CPU usage 
      self.usage_label[frame.index] = Label(frame, text='CPU Usage \n' + str(self.cpu_usage[frame.index].rstrip()),fg='white',bg='red') 
      self.usage_label[frame.index].grid(padx=20, ipady=10, pady=3,row=3, column=0, sticky='EW') 

      ### set up buttons 
      self.quit_button[frame.index] = Button(frame, text="QUIT", fg="red", command=frame.quit) 
      self.quit_button[frame.index].grid(padx=120, pady=60,row=6, column=0) 
      self.refresh_button[frame.index] = Button(frame, text="REFRESH", fg="blue", command= lambda f=frame: self.refresh(master,f)) 
      self.refresh_button[frame.index].grid(padx=20, pady=3,row=5, column=0, sticky='EW') 

      ### populate listbox 
      self.listbox = Listbox(frame, height=28, width=60) 
      self.scrollbar = ttk.Scrollbar(frame, orient=VERTICAL, command=self.listbox.yview) 
      self.listbox['yscrollcommand'] = self.scrollbar.set 
      for line in grep_results: 
       self.listbox.insert('end', str(line).rstrip()) 
       process_count+=1 
      self.scrollbar.grid(row = 0, column = 4, sticky='NSE', rowspan=8) 
      self.listbox.grid(row = 0, column = 2, columnspan = 2, sticky='E', rowspan=8) 

      ### config and display number of processes running 
      self.count_label = Label(frame, text='Perl Processes \n' + str(process_count),fg='black',bg='grey').grid(padx=20, ipady=10, pady=3,row=1, column=0, sticky='EW') 
      self.refresh_label = Label(frame, text='Last Refresh at ' + datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S') ,fg='black').grid(padx=0, ipady=0, pady=0,row=7, column=0, sticky='EW') 

     self.update(master,frame) 


    def refresh(self,master,frame): 
     # if self.usage_label[frame.index] is not None: 
     #  self.usage_label[frame.index].destroy() 
     ### execute terminal commands 
     self.cpu_usage[frame.index] = os.popen(
       "ssh -t " + frame.host_string + " grep 'cpu ' /proc/stat | awk '{usage=($2+$4)*100/($2+$4+$5)} END {print usage \"%\"}'" 
       ).read() 
     self.usage_label[frame.index].configure(text='CPU Usage \n' + str(self.cpu_usage[frame.index].rstrip())) 
     grep_results = os.popen("ls") 
     # grep_results = os.popen("ps aux | grep \"\.pl\" | grep -invertmatch grep") 
     cron_activity = os.popen("ssh -t " + frame.host_string + " \'service cron status | grep Active\'").read() 
     process_count = 0 
     self.listbox.delete(0, END) 
     # for line in grep_results: 
     #  print line 
     #  self.listbox.insert('end', str(line).rstrip()) 
     #  process_count+=1 
     # self.listbox.grid(row = 0, column = 2, columnspan = 2, sticky='E', rowspan=8) 
     self.count_label = Label(frame, text='Perl Processes \n' + str(process_count),fg='black',bg='grey').grid(padx=20, ipady=10, pady=3,row=1, column=0, sticky='EW') 
     self.refresh_label = Label(frame, text='Last Refresh at ' + datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S') ,fg='black').grid(padx=0, ipady=0, pady=0,row=7, column=0, sticky='EW') 



    # starting and stopping cron requires a password unless the user is configured not to 
    def start_cron(self,master,frame): 
     print "Starting Cron On " + frame.host_string 
     try: 
      os.system("ssh -t " + frame.host_string + " \'sudo service cron start\'") 
      print "Cron Successfully Started On " + frame.host_string 
      cron_activity = os.popen("ssh -t " + frame.host_string + " \'service cron status | grep Active\'").read() 
      if 'active (running)' in cron_activity: 
       self.cron_button[frame.index].configure(text='CRON (active)') 
       self.cron_button[frame.index].configure(bg='green') 
       self.cron_button[frame.index].configure(command= lambda: self.stop_cron(master,frame)) 
       master.update() 
     except: 
      print "Cron Failed On " + frame.host_string 



    # starting and stopping cron requires a password unless the user is configured not to 
    def stop_cron(self,master,frame): 
     print "Stopping Cron On " + frame.host_string 
     try: 
      os.system("ssh -t " + frame.host_string + " \'sudo service cron stop\'") 
      print "Cron Successfully Stopped On " + frame.host_string 
      cron_activity = os.popen("ssh -t " + frame.host_string + " \'service cron status | grep Active\'").read() 
      if 'inactive (dead)' in cron_activity: 
       self.cron_button[frame.index].configure(text='CRON (inactive)') 
       self.cron_button[frame.index].configure(bg='red') 
       self.cron_button[frame.index].configure(command= lambda: self.start_cron(master,frame)) 
       master.update() 
     except: 
      print "Cron Failed On " + frame.host_string 



    def update(self,master,frame): 
     # While the pipe has data, read and update the StringVar 
     self.refresh(master,frame) 

     # set the update method to run again in 1 seconds time 
     master.after(60000,self.update(master,frame)) 



if __name__ == "__main__": 
    main() 

답변

0

주기적으로 뭔가를 실행하기위한 기본 알고리즘은 다음과 같습니다 번이 함수를 호출 할 때, 그 다음, 당신이 원하는 무엇이든 1 분 다시 호출 할 수 자체를 예약합니다

def refresh(root): 
    <do whatever you want here> 
    root.after(60000, refresh, root) 

.

<do whatever you want here>에는 몇 백 밀리 초 밖에 걸리지 않아야합니다. 그렇지 않으면 응용 프로그램이 느려지거나 정지됩니다.

코드에서 만든 실수는 여기에 있습니다 :

master.after(60000,self.update(master,frame)) 

이것은 다음과 동일하다 :

result = self.update(master, frame) 
master.after(60000, result) 

기억해야 할 중요한 것은 after이 같은 호출이 필요하다는 것이다 밀리 초 단위의 첫 번째 인수 해당 호출 가능 함수에 인수가 필요한 경우 추가 인수로 추가 할 수 있습니다.

+0

감사합니다. @ bryan-oakley. 이것은 확실히 나에게 무언가를 가르치고 googleing과 시행 착오의 또 다른 라운드를 촉발시켰다. 나는 뭔가를 올바르게 이해하지 못한다면 전체 프로그램에 근본적으로 잘못된 것이있을 것이라고 생각합니다. 귀하의 예제에서와 같이 루트 (또는 자기 자신의 경우)를 사용하려고하면 오류'AttributeError : ProcessorWatch 인스턴스에 'after'' 속성이 없습니다. 그러나'self.update()'대신'master.update()'를 실행하려고하면 에러가 없지만'update()'는 호출되지 않습니다. ProcessorWatch를 잘못 초기화합니까? –

+0

@ThomasCannon'after'는 모든 위젯에서 사용할 수있는 방법입니다. 내 예제에서는 단순히 _any_ widget을 전달해야합니다. 귀하의 경우 '자기'는 위젯이 아니므로 오류입니다. –

+0

아! 그것은 많은 것을 명확히합니다. 고맙습니다! –

관련 문제