Domanda

Ho un comando come questo.

wmctrl -lp | awk '/gedit/ { print $1 }'

E voglio il suo output all'interno dello script Python, ho provato questo codice

>>> import subprocess
>>> proc =  subprocess.Popen(["wmctrl -lp", "|","awk '/gedit/ {print $1}"], shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
>>> proc.stdout.readline()
'0x0160001b -1 6504   beer-laptop x-nautilus-desktop\n'
>>> proc.stdout.readline()
'0x0352f117  0 6963   beer-laptop How to get output from external command combine with Pipe - Stack Overflow - Chromium\n'
>>> proc.stdout.readline()
'0x01400003 -1 6503   beer-laptop Bottom Expanded Edge Panel\n'
>>> 

Sembra che il mio codice sia sbagliato solo wmctrl -lp è stato eseguito e | awk "{print $ 1}" è stato omesso Il mio risultato atteso sarebbe 0x03800081

$ wmctrl -lp | awk '/gedit/ {print $1}'
0x03800081

Per favore, ti aiuta.

È stato utile?

Soluzione

Con shell = True , è necessario utilizzare una singola riga di comando anziché un array, altrimenti gli argomenti aggiuntivi vengono interpretati come argomenti di shell. Dalla sottoprocesso documentazione :

  

Su Unix, con shell = True: se args è una stringa, specifica la stringa di comando da eseguire attraverso la shell. Se args è una sequenza, il primo elemento specifica la stringa di comando e tutti gli elementi aggiuntivi verranno trattati come argomenti di shell aggiuntivi.

Quindi la tua chiamata dovrebbe essere:

subprocess.Popen("wmctrl -lp | sed /gedit/ '{print $1}'", shell=True, ...

Penso che potresti anche avere una sola citazione non bilanciata.

Altri suggerimenti

Poiché stai passando una sequenza per il programma, pensa che la pipe sia un argomento in wmcrtrl , come se lo avessi fatto

wmctrl -lp "|"

e quindi l'operazione pipe effettiva viene persa.

Renderlo una singola stringa dovrebbe davvero darti il ??risultato corretto:

>>> import subprocess as s
>>> proc = s.Popen("echo hello | grep e", shell=True, stdout=s.PIPE, stderr=s.PIPE)
>>> proc.stdout.readline()
'hello\n'
>>> proc.stdout.readline()
''

Dopo alcune ricerche, ho il seguente codice che funziona molto bene per me. Fondamentalmente stampa sia stdout che stderr in tempo reale. Spero che aiuti qualcun altro che ne abbia bisogno.

stdout_result = 1
stderr_result = 1


def stdout_thread(pipe):
    global stdout_result
    while True:
        out = pipe.stdout.read(1)
        stdout_result = pipe.poll()
        if out == '' and stdout_result is not None:
            break

        if out != '':
            sys.stdout.write(out)
            sys.stdout.flush()


def stderr_thread(pipe):
    global stderr_result
    while True:
        err = pipe.stderr.read(1)
        stderr_result = pipe.poll()
        if err == '' and stderr_result is not None:
            break

        if err != '':
            sys.stdout.write(err)
            sys.stdout.flush()


def exec_command(command, cwd=None):
    if cwd is not None:
        print '[' + ' '.join(command) + '] in ' + cwd
    else:
        print '[' + ' '.join(command) + ']'

    p = subprocess.Popen(
        command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, cwd=cwd
    )

    out_thread = threading.Thread(name='stdout_thread', target=stdout_thread, args=(p,))
    err_thread = threading.Thread(name='stderr_thread', target=stderr_thread, args=(p,))

    err_thread.start()
    out_thread.start()

    out_thread.join()
    err_thread.join()

    return stdout_result + stderr_result

Se necessario, penso che sia facile raccogliere l'output o l'errore in una stringa e restituirlo.

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