2012-04-03 2 views
37
import os 

import subprocess 

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

out,err = proc.communicate() 

print out 

Questo script dovrebbe stampare tutti i file con suffisso .bc, tuttavia restituisce una lista vuota. Se faccio ls * .bc manualmente nella riga di comando funziona. Anche fare ['ls', 'test.bc'] all'interno dello script funziona bene, ma per qualche motivo il simbolo stella non funziona. Qualche idea?Utilizzo jolly subprocesso Python

+0

correlati: [jolly non funziona nella chiamata di sottoprocesso usando shlex] (http: // stackoverf low.com/q/7156892/4279) – jfs

risposta

41

È necessario fornire shell=True per eseguire il comando tramite un interprete di shell. Se lo fai, tuttavia, non puoi più fornire un elenco come primo argomento, perché gli argomenti verranno citati in quel momento. Al contrario, specificare la riga di comando crudo come si desidera essere passato alla shell:

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

Grazie a questo ha funzionato bene. Alcuni degli esempi che ho trovato su Internet avevano una lista come primo argomento per qualche motivo – Cemre

+9

@Cemre: Di solito è consigliabile perché * non * vuole che la shell interpreti gli argomenti. Immagina di passare l'input dell'utente a un comando come in ''ls' + user_supplied_path'. L'utente potrebbe semplicemente inserire il percorso '; shutdown -s' e il sistema si fermerebbe! Se usi '['ls', user_supplied_path]', previeni questo tipo di iniezione. –

37

Ampliare la * glob fa parte del guscio, ma probabilmente la subprocess fa non inviare i comandi tramite una shell, in modo il comando (primo argomento, ls) viene eseguito, quindi un letterale * viene utilizzato come argomento.

Questa è una buona cosa, vedere the warning block in the "Frequently Used Arguments" section, dei documenti di sottoprocesso. Principalmente discute le implicazioni di sicurezza, ma può anche aiutare a evitare errori di programmazione stupidi (poiché non ci sono caratteri di shell magici di cui preoccuparsi)

La mia lamentela principale con shell=True è di solito implica che c'è un modo migliore per risolvere il problema - con il tuo esempio, si dovrebbe usare the glob module:

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

Questo sarà più veloce (non di avvio di processo in testa), più affidabile e multipiattaforma (non dipendente dalla piattaforma di avere un comando ls)

+0

'il sottoprocesso non invia i comandi tramite una shell' Perché? Potete fornire qualche riferimento? Grazie – Stallman

+0

Inoltre, dà un oggetto Python con cui lavorare e manipolare. Questa dovrebbe essere la risposta selezionata. Molto più amichevole di 'python'. – Cyan