2012-04-03 15 views
37
import os 

import subprocess 

proc = subprocess.Popen(['ls','*.bc'], stdout=subprocess.PIPE, stderr=subprocess.PIPE) 

out,err = proc.communicate() 

print out 

Dieses Skript sollte alle Dateien mit .bc-Suffix drucken, es wird jedoch eine leere Liste zurückgegeben. Wenn ich ls * .bc manuell in der Befehlszeile mache, funktioniert es. Doing ['ls', 'test.bc'] innerhalb des Skripts funktioniert auch, aber aus irgendeinem Grund funktioniert das Sternsymbol nicht .. Irgendwelche Ideen?Python-Subprozess-Platzhalter Verwendung

+0

bezogen: mit Ihrem Beispiel sollen Sie the glob module verwenden [Wildcard funktioniert nicht im Subprozess-Aufruf mit shlex] (http: // stackoverf low.com/q/7156892/4279) – jfs

Antwort

41

Sie müssen shell=True angeben, um den Befehl über einen Shell-Interpreter auszuführen. Wenn Sie dies jedoch tun, können Sie keine Liste mehr als erstes Argument angeben, da die Argumente dann in Anführungszeichen gesetzt werden. Stattdessen geben Sie die rohe Kommandozeile, wie Sie es wollen an die Shell übergeben werden:

proc = subprocess.Popen('ls *.bc', shell=True, 
            stdout=subprocess.PIPE, 
            stderr=subprocess.PIPE) 
+0

Danke, das hat gut funktioniert. Einige der Beispiele, die ich im Internet gefunden habe, hatten aus irgendeinem Grund eine Liste als ihr erstes Argument. – Cemre

+9

@Cemre: Das ist normalerweise ratsam, weil Sie nicht wollen, dass die Shell die Argumente interpretiert. Stellen Sie sich vor, Sie übergeben Benutzereingaben an einen Befehl wie in '' ls '+ user_supplied_path'. Der Benutzer könnte einfach den Pfad eingeben; shutdown -s' und das System würde anhalten! Wenn Sie '['ls', user_supplied_path]' verwenden, verhindern Sie diese Art der Injektion. –

37

die * glob Erweiterung Teil der Schale ist, aber standardmäßig subprocess tut nicht Ihre Befehle über eine Shell schicken, so der Befehl (erstes Argument, ls) wird ausgeführt, dann wird ein Literal * als Argument verwendet.

Dies ist eine gute Sache, siehe the warning block in the "Frequently Used Arguments" section, der Subprozessdokumente. Es behandelt hauptsächlich die Auswirkungen auf die Sicherheit, kann aber auch dazu beitragen, dumme Programmierfehler zu vermeiden (da es keine magischen Shell-Zeichen gibt)

Meine Hauptbeschwerde mit shell=True ist normalerweise, dass es einen besseren Weg gibt, das Problem zu lösen

import glob 
files = glob.glob("*.bc") 
print files # ['file1.bc', 'file2.bc'] 

Dies wird schneller sein (kein Prozess Startup-Overhead), zuverlässige und Cross-Plattform (nicht abhängig von der Plattform einen ls Befehl mit)

+0

'subprocess sendet Ihre Befehle nicht über eine Shell' Warum? Können Sie eine Referenz angeben? Danke – Stallman

+0

Plus gibt es ein Python-Objekt, mit dem man arbeiten und manipulieren kann. Dies sollte die ausgewählte Antwort sein. Viel mehr 'Python' freundlich. – Cyan

Verwandte Themen