Ausführungssystembefehle in Python mit Flüchen und Panel und kehren Sie zum vorherigen Menü zurück

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

Frage

Ich kodiere ein Python -Skript mit mehreren Commanline -Tools wie Top, daher brauche ich ein richtiges visuelles Feedback. Jetzt ist es Zeit, ihm ein Menü zu geben, also kommt hier das Problem.

Ich fand hier einen tollen Ansatz Von dem, was ich brauche, aber jeder Versuch, ein Feedback zu zeigen, bevor ich wieder zum vorherigen Menü zurückkehrt, ist zwecklos.

Ich brauche nur Menüs, Untermenüs, Startbefehle, beenden sie und kehrt zum vorherigen Menü zurück. Ein großer Bonus wäre, sie in einer Aufteilung des Begriffs zu betreiben.

Gibt es ein Muster/Skelett/Zeug/was auch immer als Vorlage, um eine gewisse Art von Widget mit einer vorhersehbaren Ausgabe anzuzeigen?

Hier ist ein Beispiel für Code, das zwei Beispiele für Funktionen ausführen müssen:

#!/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)

Vielen Dank an Rat (und Entschuldigung für mein hartes Englisch)

War es hilfreich?

Lösung

Sie haben wirklich zwei Möglichkeiten. Sie können den Flüchenmodus hinterlassen, Ihr Programm ausführen und dann Flüche wieder aufnehmen. Zweitens können Sie Ihr Programm asynchron ausführen, seine Ausgabe analysieren und auf den Bildschirm schreiben.

Die gute Nachricht zur ersten Option ist, dass Sie keine Fancy Save_State / Load_State -Methoden für die Benutzeroberfläche schreiben müssen. Flüche tun dies für Sie. Hier ist ein einfaches Beispiel, um meinen Standpunkt zu zeigen

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)

Wenn Sie das Beispiel ausführen, werden Sie feststellen, dass der Bildschirm von erstellt wurde curses.wrapper und der in erstellte in curses.initscr Bei der Wiederaufnahme sind das gleiche Objekt. Das heißt, das Fenster wurde von zurückgegeben curses.initscr ist ein Singleton. Auf diese Weise können wir Flüche beenden und wie oben wieder aufnehmen, ohne jedes Widget aktualisieren zu müssen self.screen Referenzen jedes Mal.

Die zweite Option ist viel besser, aber auch viel flexibler. Das Folgende ist nur die Grundidee darzustellen.

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()

Dann möchten Sie irgendwo in Ihrem Programm anrufen update Bei all Ihren Procwidgets auf einem Timer. Dies gibt Ihnen die Möglichkeit, Ihren Unterwindow zu jeder Größe/einem Ort zu machen, sodass Sie so viele Procwidgets haben können, wie sie passen werden. Sie müssen ein gewisses Handling hinzufügen, wenn der Prozess endet und natürlich ähnliche Ereignisse.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top