Curses 및 패널을 사용하여 Python에서 시스템 명령 실행 및 이전 메뉴로 돌아 오십시오.

StackOverflow https://stackoverflow.com/questions/19833315

문제

Top과 같은 여러 Commanline 도구를 사용하여 Python 스크립트를 코딩하고 있으므로 적절한 시각적 피드백이 필요합니다. 이제 메뉴를 줄 시간이므로 여기에 문제가 있습니다.

나는 여기서 훌륭한 접근법을 찾았습니다 내가 필요로하는 것들에 대해서는 이전 메뉴로 돌아 오기 전에 피드백을 표시하려고 시도하는 것은 쓸모가 없습니다.

메뉴, 하위 메뉴, 실행 명령, 종료 및 이전 메뉴로 돌아 가면됩니다. 큰 보너스는 용어의 분할에서 그것들을 실행하는 것입니다.

예측 가능한 출력으로 여러 종류의 위젯을 표시하기 위해 템플릿으로 사용할 패턴/스켈레톤/스테르/템플릿이 있습니까?

다음은 코드의 예입니다. 두 가지 기능을 실행할 기능입니다.

#!/usr/bin/env python2                                                       

import curses                                                                
from curses import panel                                                     

class Menu(object):                                                          

    def __init__(self, items, stdscreen):                                    
        self.window = stdscreen.subwin(0,0)                                  
        self.window.keypad(1)                                                
        self.panel = panel.new_panel(self.window)                            
        self.panel.hide()                                                    
        panel.update_panels()                                                

        self.position = 0                                                    
        self.items = items                                                   
        self.items.append(('exit','exit'))                                   

    def navigate(self, n):                                                   
        self.position += n                                                   
        if self.position < 0:                                                
            self.position = 0                                                
        elif self.position >= len(self.items):                               
            self.position = len(self.items)-1                                

    def display(self):                                                       
        self.panel.top()                                                     
        self.panel.show()                                                    
        self.window.clear()                                                  

        while True:                                                          
            self.window.refresh()                                            
            curses.doupdate()                                                
            for index, item in enumerate(self.items):                        
                if index == self.position:                                   
                    mode = curses.A_REVERSE                                  
                else:                                                        
                    mode = curses.A_NORMAL                                   

                msg = '%d. %s' % (index, item[0])                            
                self.window.addstr(1+index, 1, msg, mode)                    

            key = self.window.getch()                                        

            if key in [curses.KEY_ENTER, ord('\n')]:                         
                if self.position == len(self.items)-1:                       
                    break                                                    
                else:                                                        
                    self.items[self.position][1]()                           

            elif key == curses.KEY_UP:                                       
                self.navigate(-1)                                            

            elif key == curses.KEY_DOWN:                                     
                self.navigate(1)                                             

        self.window.clear()                                                  
        self.panel.hide()                                                    
        panel.update_panels()                                                
        curses.doupdate()

######################################################### !# 
######################################################### !#    
############# HERE MY FUNCTIONS examples
############  Everithing works OK, but displays it awfully

def GetPid(name):
    import subprocess
    command= str(("""pgrep %s""") % name )
    p = subprocess.Popen(command, shell = True, stdout = subprocess.PIPE)
    procs = []
    salida = p.stdout
    for line in salida:
        procs.append(str.strip(line))

    return procs


def top():
    os.system("top")    

def menuGP():
    print GetPid("top")  


######################################################### !# 

class MyApp(object):                                                         

    def __init__(self, stdscreen):                                           
        self.screen = stdscreen                                              
        curses.curs_set(0)                                                   

        submenu_items = [                                                    
                ('beep', curses.beep),                                       
                ('top', top)                                      
                ]                                                            
        submenu = Menu(submenu_items, self.screen)                           

        main_menu_items = [                                                  
                ('get PID', GetPid),                                       
                ('submenu', submenu.display)                                 
                ]                                                            
        main_menu = Menu(main_menu_items, self.screen)                       
        main_menu.display()                                                  

if __name__ == '__main__':                                                       
    curses.wrapper(MyApp)

조언에 감사드립니다 (그리고 내 거친 영어에 대해 죄송합니다)

도움이 되었습니까?

해결책

당신은 정말로 두 가지 선택이 있습니다. 하나는 Curses 모드를 남기고 프로그램을 실행 한 다음 Curses를 재개 할 수 있습니다. 둘째, 프로그램을 비동기로 실행하고 출력을 구문 분석하고 화면에 쓸 수 있습니다.

첫 번째 옵션에 대한 좋은 소식은 실제로 UI에 대한 멋진 save_state / load_state 메소드를 작성할 필요가 없다는 것입니다. 저주는 당신을 위해 이것을합니다. 다음은 내 요점을 보여주는 간단한 예입니다

import curses, time, subprocess

class suspend_curses():
    """Context Manager to temporarily leave curses mode"""

    def __enter__(self):
        curses.endwin()

    def __exit__(self, exc_type, exc_val, tb):
        newscr = curses.initscr()
        newscr.addstr('Newscreen is %s\n' % newscr)
        newscr.refresh()
        curses.doupdate()

def main(stdscr):
    stdscr.addstr('Stdscreen is %s\n' % stdscr)
    stdscr.refresh()
    time.sleep(1)

    with suspend_curses():
        subprocess.call(['ls'])
        time.sleep(1)

    stdscr.refresh()
    time.sleep(5)

curses.wrapper(main)

예제를 실행하면 curses.wrapper 그리고 창조 된 것 curses.initscr 재개시 같은 객체입니다. 즉, 창문이 반환되었습니다 curses.initscr 싱글 톤입니다. 이를 통해 각 위젯의 업데이트없이 저주를 종료하고 위의 이력서를 이용할 수 있습니다. self.screen 매번 참조.

두 번째 옵션은 훨씬 더 관여하지만 훨씬 유연합니다. 다음은 단지 기본 아이디어를 나타내는 것입니다.

class procWidget():
    def __init__(self, stdscr):
        # make subwindow / panel
        self.proc = subprocess.Popen(my_args, stdout=subprocess.PIPE)

    def update(self):
        data = self.proc.stdout.readline()
        # parse data as necessary
        # call addstr() and refresh()

그런 다음 프로그램 어딘가에 전화하고 싶을 것입니다. update 타이머의 모든 procwidget에. 이렇게하면 하위 바람이 모든 크기/장소를 만들 수 있도록 옵션을 제공하므로 적합한 많은 ProcWidget을 가질 수 있습니다. 프로세스가 종료 될 때 및 기타 유사한 이벤트에 대한 처리를 추가해야합니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top