Commandes du système en cours d'exécution dans Python à l'aide de malédictions et de panneau, et revenez au menu précédent

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

Question

Je codage un script Python à l'aide de plusieurs outils Commanline comme TOP, j'ai donc besoin d'une rétroaction visuelle appropriée. Il est maintenant temps de lui donner un menu, alors voici le problème.

J'ai trouvé ici une grande approche de ce dont j'ai besoin, mais chaque essai d'afficher une rétroaction avant de revenir au menu précédent est futile.

J'ai juste besoin de menus, de sous-menus, de lancement de commandes, de le terminer et de revenir au menu précédent. Un grand bonus serait de les faire fonctionner dans une scission du terme.

Y a-t-il un motif / squelette / des trucs / quoi que ce soit à utiliser comme modèle afin d'afficher plusieurs types de widgets avec une sortie prévisible?

Voici un exemple de code, que deux exemples de fonctions à exécuter:

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

Merci en conseillant (et désolé pour mon anglais brut)

Était-ce utile?

La solution

Vous avez vraiment deux choix. Celui que vous pouvez laisser le mode malédiction, exécuter votre programme, puis reprendre les malédictions. Deux, vous pouvez exécuter votre programme de manière asynchrone, analyser sa sortie et l'écrire à l'écran.

La bonne nouvelle sur la première option est que vous n'avez pas vraiment besoin d'écrire des méthodes SAVE_STATE / LOAD_STATE pour l'interface utilisateur. Les malédictions font cela pour vous. Voici un exemple simple pour montrer mon point

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)

Si vous exécutez l'exemple, vous remarquerez que l'écran créé par curses.wrapper Et celui créé dans curses.initscr Lors du reprise sont le même objet. C'est-à-dire que la fenêtre est retournée par curses.initscr est un singleton. Cela nous permet de quitter les malédictions et de reprendre comme ci-dessus sans avoir à mettre à jour chaque widget self.screen références à chaque fois.

La deuxième option est beaucoup plus impliquée mais aussi beaucoup plus flexible. Ce qui suit est simplement de représenter l'idée de base.

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

Ensuite, quelque part dans votre programme, vous voudrez appeler update sur tous vos Prowidgets sur une minuterie. Cela vous donne la possibilité de faire de votre sous-fenêtre n'importe quelle taille / lieu afin que vous puissiez avoir autant de Prowidgets que cela conviendra. Vous devrez ajouter un peu de traitement lorsque le processus se termine et d'autres événements similaires bien sûr.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top