2012-03-11 2 views
10

Mi piacerebbe usare sottoprocesso sulla riga seguente:Sottoprocesso Python: come usare i tubi tre volte?

convert ../loxie-orig.png bmp:- | mkbitmap -f 2 -s 2 -t 0.48 | potrace -t 5 --progress -s -o ../DSC00232.svg 

ho trovato grazie ad altri posti the subprocess documentation ma nell'esempio usiamo solo il tubo due volte.

Così, provo per due dei tre comandi e funziona

p1 = subprocess.Popen(['convert', fileIn, 'bmp:-'], stdout=subprocess.PIPE) 
# p2 = subprocess.Popen(['mkbitmap', '-f', '2', '-s', '2', '-t', '0.48'], stdout=subprocess.PIPE) 
p3 = subprocess.Popen(['potrace', '-t' , '5', '-s' , '-o', fileOut], stdin=p1.stdout,stdout=subprocess.PIPE) 
p1.stdout.close() # Allow p1 to receive a SIGPIPE if p3 exits. 
output = p3.communicate()[0] 

mi potete aiutare per il terzo comando?

Grazie mille.

+1

hai provato di nuovo per la terza comando con lo stesso processo? –

+0

Perché non ha funzionato quello che hai provato? Tutto il pipe fa in una shell è lo stdout di un processo per stdinne un altro. – Dunes

+0

Non so dove devo chiudere p2 e come codificare l'output ... – Zorkzyd

risposta

19

Basta aggiungere un terzo comando seguendo lo stesso esempio:

p1 = subprocess.Popen(['convert', fileIn, 'bmp:-'], stdout=subprocess.PIPE) 
p2 = subprocess.Popen(['mkbitmap', '-f', '2', '-s', '2', '-t', '0.48'], 
    stdin=p1.stdout, stdout=subprocess.PIPE) 
p1.stdout.close() 
p3 = subprocess.Popen(['potrace', '-t' , '5', '-s' , '-o', fileOut],   
    stdin=p2.stdout,stdout=subprocess.PIPE) 
p2.stdout.close() 

output = p3.communicate()[0] 
+0

Non ci credo, ora che sono tutti collegati penso che dovrebbe essere necessaria solo una chiamata 'communicate'. Ha funzionato? –

+0

Sì, funziona ora. Grazie :) – Zorkzyd

+2

Ha importanza se 'p1.stdout.close()' e 'p2.stdout.close()' vieni dopo 'output = p3.communicate() [0]'? – sandyp

5

Utilizzare subprocess.Popen() con l'opzione shell=True, e si può passare l'intero comando come una singola stringa.

+0

Questa è spesso la strada da percorrere (è sicuramente molto più semplice) ma a volte è possibile imbattersi in problemi di quotatura del nome file, ad esempio, se "fileIn" o "fileOut" hanno uno spazio nel nome. Si può usare 'pipes.quote' per gestirli il più delle volte, ma lasciare' shell = False 'è tecnicamente più sicuro. – torek

1
def runPipe(cmds): 
try: 
    p1 = subprocess.Popen(cmds[0].split(' '), stdin = None, stdout = subprocess.PIPE, stderr = subprocess.PIPE) 
    prev = p1 
    for cmd in cmds[1:]: 
     p = subprocess.Popen(cmd.split(' '), stdin = prev.stdout, stdout = subprocess.PIPE, stderr = subprocess.PIPE) 
     prev = p 
    stdout, stderr = p.communicate() 
    p.wait() 
    returncode = p.returncode 
except Exception, e: 
    stderr = str(e) 
    returncode = -1 
if returncode == 0: 
    return (True, stdout.strip().split('\n')) 
else: 
    return (False, stderr) 

eseguirlo come:

runPipe(['ls -1','head -n 2', 'head -n 1'])