2016-06-03 7 views
2

Ich habe Probleme mit der Konvertierung von Bash-Shell zu Python3.Konvertieren von Bash-Shell zu Python3 mit Subprocess.Popen()

Hier Shell-Befehl, den ich Python konvertieren möchten:

cat $outDir/aDir/* | cut -f2 | sort -u > $outDir/outFile.txt 

ich bereits subprocess.call() verwenden und es hat funktioniert, aber ich möchte wissen, wie es mit Popen machen().

Hier ist mein Code, der nicht funktioniert hat:

import subprocess 
import glob 

filePath = outDir + 'aDir/*' 
outFilePath = outDir + '/outFile.txt' 

fileList = [] 
for files in glob.glob(filePath): 
    fileList.append(files) 
with open(files, 'r') as inFile, open(outFilePath, 'w') as outFile : 
    p = subprocess.Popen(['cat'], stdin=inFile, stdout=subprocess.PIPE) 
    p2 = subprocess.Popen(['cut', '-f2'], stdin = p1.stdout, stdout=subprocess.PIPE) 
    p3 = subprocess.Popen(['sort', '-u'], stdin = p2.stdout, stdout = outFile) 

und könnten Sie erklären, warum shell=True schädlich ist? Ich sah es in vielen Antworten, aber ich weiß nicht warum ...

Vielen Dank.

+1

http://stackoverflow.com/questions/3172470/actual-meaning-of-shell-true-in-subprocess erklärt, warum Sie 'shell = True' vermeiden möchten. – tripleee

+0

@tripleee: und [dies zeigt, dass 'shell = True' nützlich sein kann] (http://stackoverflow.com/q/295459/4279) (Wenn es keine nicht vertrauenswürdigen Eingaben gibt, ist es wahrscheinlicher, dass ein Fehler gemacht wird.) während die Shell-Pipeline unter Verwendung von 'subprocess.Popen' direkt neu implementiert wird, als man einen Fehler aufgrund von Inkompatibilitäten für einen einfachen Shell-Befehl erhält. – jfs

+0

Das Problem ist nicht, dass es nutzlos ist, sondern dass es Verständnis erfordert. Die Shell hat die unglückliche Ehre, proportional mehr Benutzer zu haben, die nicht einmal die absoluten Grundlagen kennen, die sogar PHP und VBscript kombiniert haben. (Diese Frage ist in dieser Hinsicht deutlich über dem Durchschnitt.) – tripleee

Antwort

2

Sie müssen eine Liste von Dateien zu cat So sollte

subprocess.Popen(['cat'], stdin=inFile, stdout=subprocess.PIPE) 

subprocess.Popen(['cat'] + [fileList], stdout=subprocess.PIPE) 

werden passieren und folglich inFile sollten nicht mehr

Also, alles in allem

benötigt werden
import subprocess 
import glob 

filePath = outDir + '/aDir/*' 
outFilePath = outDir + '/outFile.txt' 

fileList = glob.glob(filePath) 
with open(outFilePath, 'w') as outFile: 
    subprocess.Popen(['cat'] + [fileList], stdout=subprocess.PIPE) 
    p2 = subprocess.Popen(['cut', '-f2'], stdin = p1.stdout, stdout=subprocess.PIPE) 
    p3 = subprocess.Popen(['sort', '-u'], stdin = p2.stdout, stdout = outFile) 
0

Wie wäre es, nur shell=True zu verwenden und die Rohre zu behalten?

with open(files, 'r') as inFile, open(outFilePath, 'w') as outFile : 
    p = subprocess.Popen('cut -f2 | sort -u', shell=True, stdin=filePath, stdout=subprocess.PIPE) 
    p.communicate() 

Oder auch, einfacher:

p = subprocess.Popen("cat {} | cut -f2 | sort -u > '{}'".format(filePath, outFilePath), shell=True) 
p.communicate() 

Oder sogar mehr einfach (dank @tripleee!):

subprocess.call("cat {} | cut -f2 | sort -u > '{}'".format(filePath, outFilePath), shell=True) 

Was shell=True, die einzige Gefahr ist wirklich, wenn Ihre Eingabe ist nicht sicher. Ich würde empfehlen, alle Eingaben mit einfachen Anführungszeichen zu versehen und alle Eingaben zu entfernen und zu bereinigen.

+0

Wenn "in" funky Zeug enthält, müssen Sie zusätzliche Schritte ausführen, um es aus der Shell-Interpretation zu entkommen. – tripleee

+0

'öffnen (Dateien, 'r')' wirft einfach einen Fehler, wenn 'Dateien' eine Liste ist. – tripleee

+0

Und sobald Sie diese Dinge behoben haben, ist 'subprocess.Popen' nur unbequem; Verwenden Sie stattdessen "subprocess.call". – tripleee