I comandi di sistema in esecuzione in Python usando maledizioni e pannelli e torna al menu precedente

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

Domanda

Sto codificando uno script Python usando diversi strumenti Commanline come TOP, quindi ho bisogno di un feedback visivo adeguato. Ora è il momento di dargli un menu, quindi ecco il problema.

Ho trovato qui un ottimo approccio Di ciò di cui ho bisogno, ma ogni tentativo di visualizzare un feedback prima di tornare al menu precedente è inutile.

Ho solo bisogno di menu, sottomeni, comandi di lancio, terminarlo e tornare al menu precedente. Un grande bonus sarebbe quello di eseguirli in una divisione del termine.

Esiste un modello/scheletro/roba/qualsiasi cosa da usare come modello per visualizzare diversi tipi di widget con un output prevedibile?

Ecco un esempio di codice, che due esempi di funzioni da eseguire:

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

Grazie in consulenza (e scusa per il mio inglese duro)

È stato utile?

Soluzione

Hai davvero due scelte. Uno che puoi lasciare la modalità maledizione, eseguire il programma, quindi riprendere le maledizioni. Due, puoi eseguire il tuo programma in modo asincrono, analizzare il suo output e scriverlo sullo schermo.

La buona notizia sulla prima opzione è che in realtà non è necessario scrivere alcun metodo SAVE_STATE / CAROD_STATE Fancy per l'interfaccia utente. Le maledizioni lo fanno per te. Ecco un semplice esempio per mostrare il mio punto

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)

Se esegui l'esempio, noterai che lo schermo creato da curses.wrapper e quello creato in curses.initscr Quando si riprendono sono lo stesso oggetto. Cioè, la finestra è tornata da curses.initscr è un singleton. Questo ci consente di uscire dalle maledizioni e riprendere come sopra senza dover aggiornare ogni widget self.screen Riferimenti ogni volta.

La seconda opzione è molto più coinvolta ma anche molto più flessibile. Quello che segue è solo rappresentare l'idea di 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()

Quindi da qualche parte nel tuo programma vorrai chiamare update Su tutti i tuoi procwidget su un timer. Questo ti dà la possibilità di realizzare il tuo sottobusto in qualsiasi dimensione/luogo in modo da poter avere tutte le procwidget che si adatteranno. Dovrai aggiungere un po 'di gestione per quando il processo termina e altri eventi simili ovviamente.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top