2013-07-19 8 views
17

Jeśli uruchomię echo a; echo b w bashu, wynikiem będzie wykonanie obu poleceń. Jednak jeśli używam podprocesu, uruchamiane jest pierwsze polecenie, drukując całą resztę linii. Kod poniżej echa a; echo b zamiast a b, jak mogę go uruchomić, aby uruchomić oba polecenia?uruchamianie wielu poleceń bash z podprocesiem

import subprocess, shlex 
def subprocess_cmd(command): 
    process = subprocess.Popen(shlex.split(command), stdout=subprocess.PIPE) 
    proc_stdout = process.communicate()[0].strip() 
    print proc_stdout 

subprocess_cmd("echo a; echo b") 
+1

powiązanymi: Tu jest [jak uruchomić wiele poleceń powłoki (i ewentualnie uchwycić ich wyjście) równoczesnie] (http://stackoverflow.com/a/23616229/4279) – jfs

Odpowiedz

37

Musisz użyć shell = True w podproces i nie shlex.split:

def subprocess_cmd(command): 
    process = subprocess.Popen(command,stdout=subprocess.PIPE, shell=True) 
    proc_stdout = process.communicate()[0].strip() 
    print proc_stdout 

subprocess_cmd('echo a; echo b') 

Powroty:

a 
b 
+1

Ah Widzę, miałem testowane 'shell = True', ale command.split() go łamał (lista). Uwaga dla innych osób czytających, użycie 'shell = True' jest zagrożeniem bezpieczeństwa, upewnij się, że masz zaufanie do danych wejściowych. – Paul

+2

Nie można użyć 'command.split()' z 'shell = True'. W rzeczywistości argument 'subprocess.Popen' z' shell = True' musi być ciągiem, a nie listą. – bougui

+0

Stwierdziłem, że jest to nieco prostsze i nie posiadałem garbowania danych wyjściowych: def do_shell (self, command): self.proc = subprocess.Popen (command, shell = True) self.proc.wait () –

0
>>> command = "echo a; echo b" 
>>> shlex.split(command); 
    ['echo', 'a; echo', 'b'] 

tak, problem jest moduł shlex nie obsługują ";"

+0

command.split() daje '['echo', 'a;', 'echo', 'b']' a także kończy się niepowodzeniem. ' – Paul

+1

@bougui ma rację. Ustaw "shell = True", pierwszy argument Popen wymaga ciągi poleceń jak "echo a; echo b". i bez "shell = True" pierwszym argumentem Popen powinna być lista, na przykład: ["echo", "a"] –

13

Właśnie natknąłem się na sytuacji, w której musiałem uruchomić kilka linii kodu bash (nierozdzielone średnikami) z poziomu Pythona. W tym scenariuszu proponowane rozwiązania nie pomagają. Jednym z nich byłoby zapisanie pliku, a następnie uruchomienie go pod numerem Popen, ale w mojej sytuacji było to niemożliwe.

Co skończyło się robi coś takiego jak:

commands = ''' 
echo "a" 
echo "b" 
echo "c" 
echo "d" 
''' 

process = subprocess.Popen('/bin/bash', stdin=subprocess.PIPE, stdout=subprocess.PIPE) 
out, err = process.communicate(commands) 
print out 

Więc najpierw utworzyć proces bash dziecko i po co to mówię do wykonania. To podejście usuwa ograniczenia przekazywania polecenia bezpośrednio do konstruktora Popen.

+1

'subprocess.check_output (commands, shell = True)' działa dobrze. Jeśli w komendach znajdują się bash-izmy, wówczas należy przekazać 'executable = '/ bin/bash''. – jfs

+1

Dla Pythona 3 możesz użyć: 'out, err = process.communicate (commands.encode ('utf-8'))' i 'print (out.decode ('utf-8'))' –

4

Łączenie poleceń z "& &".

os.system('echo a > outputa.txt && echo b > outputb.txt') 
+1

Drugi nie uruchomi się, jeśli pierwsze polecenie zawiera błąd. Powiedziałbym, użyj; zamiast. – NateW

1

Jeśli używasz tylko komendy w jednym ujęciu, to możesz po prostu użyć subprocess.check_output funkcję Wygoda:

def subprocess_cmd(command): 
    output = subprocess.check_output(command, shell=True) 
    print output