2015-06-15 15 views
5

Nel mio progetto corrente ho un server web che chiama comandi Linux per ottenere informazioni che vengono poi visualizzate sul sito web. Il problema che ho con questo è che il server web viene eseguito su un piccolo dispositivo incorporato (è fondamentalmente uno strumento di configurazione per il dispositivo) che ha solo 256 MB di RAM. Il server web in sé richiede più della metà della RAM gratuita che ho su quel dispositivo.subprocesso.check_output senza utilizzo di memoria elevato

Ora, quando provo a utilizzare subprocess.check_output() per chiamare un comando, la forcella raddoppia l'utilizzo della RAM (perché clona il processo padre o qualcosa del genere, per quanto ho capito) e quindi arresta il tutto con un "Memoria insufficiente", sebbene il processo chiamato sia piuttosto piccolo.

Poiché il dispositivo utilizza chip flash a basso costo che si sono dimostrati inefficaci in caso di uso eccessivo, non desidero utilizzare soluzioni di swap o altre soluzioni basate sull'aumento della memoria virtuale.

Quello che ho cercato di fare finora è di aprire una sessione SH all'inizio del programma quando è ancora basso sull'utilizzo della memoria e quindi scrivere i comandi su quella sessione e leggere l'output. Funziona così, ma è abbastanza instabile, dal momento che una "uscita" sbagliata o qualcosa di simile può mandare in crash tutto.

Esiste una soluzione simile a subprocess.check_output() che non raddoppia l'utilizzo della memoria?

+0

Che server Web stai utilizzando btw? –

+0

È un programma auto-programmato che utilizza web.py come framework. – Dakkaron

+0

Cura di postarlo da qualche parte in modo che possiamo prendere un gander? –

risposta

5

Quindi con l'aiuto di J.F. Sebastian ho capito.

Questo è il codice che ho usato alla fine:

multiprocessing.set_start_method
from multiprocessing import Process, Queue 
from subprocess import check_output, CalledProcessError 

def cmdloop(inQueue,outQueue): 
    while True: 
     command = inQueue.get() 
     try: 
      result = check_output(command,shell=True) 
     except CalledProcessError as e: 
      result = e 

     outQueue.put(result) 

inQueue = Queue() 
outQueue = Queue() 
cmdHostProcess = Process(target=cmdloop, args=(inQueue,outQueue,)) 
cmdHostProcess.start() 

def callCommand(command): 
    inQueue.put(command) 
    return outQueue.get() 

def killCmdHostProcess(): 
    cmdHostProcess.terminate() 

In Python 3.4+ avrei potuto usare ('forkserver'), ma dal momento che questo viene eseguito su Python 2.7 questo è purtroppo non disponibile .

Ancora questo riduce il mio utilizzo della memoria da un lungo tiro e rimuove il problema in modo pulito. Grazie mille per l'aiuto!

+1

Questa è una buona soluzione al problema, ma il fatto che Python lo renda necessario in primo luogo è terribile. –

+0

Bella soluzione! Vale la pena ricordare che non dovresti usare 'shell = True' leggermente come accennato anche nella documentazione su https://docs.python.org/2/library/subprocess.html#frequently-used-arguments e forse ha anche un effetto negativo sull'utilizzo della RAM (due forcelle invece di una forse?). Inoltre potresti voler catturare 'OSError's. – phk

+0

Hai qualche prova che ci sia un sovraccarico significativo su questa copia extra? AFAIK il Copy-on-write dovrebbe evitare questo sovraccarico. – Mohit

Problemi correlati