2011-02-11 12 views
64

Co zrobić w wierszu poleceń:Python: Jak przekierować wyjście z podprocesorem?

cat file1 file2 file3 > myfile 

Co chcę zrobić z python:

import subprocess, shlex 
my_cmd = 'cat file1 file2 file3 > myfile' 
args = shlex.split(my_cmd) 
subprocess.call(args) # spits the output in the window i call my python program 
+0

Wykonywanie takiego polecenia w podprocesie nie dawałoby żadnych wyników. Może chcesz go uruchomić bez _> myfile_ przekierowującego wyjście z _cat file1 file2 file3_ do python? – PoltoS

+0

@PoltoS Chcę dołączyć do niektórych plików, a następnie przetworzyć wynikowy plik. Myślałem, że używanie kota jest najłatwiejszą alternatywą. Czy istnieje lepszy/pythonic sposób to zrobić? – catatemypythoncode

+0

Rozwiązanie oparte na 'os.sendfile()' jest możliwe, patrz [Odwzoruj polecenie unix cat w pythonie] (http://stackoverflow.com/q/11532980/4279) – jfs

Odpowiedz

23

UPDATE: os.system jest zniechęcony, aczkolwiek nadal dostępne w Pythonie 3.


Zastosowanie os.system:

os.system(my_cmd) 

Jeśli naprawdę chcesz używać podproces, oto rozwiązanie (głównie podnoszone z dokumentacją podproces):

p = subprocess.Popen(my_cmd, shell=True) 
os.waitpid(p.pid, 0) 

OTOH można uniknąć układ połączeń w całości:

import shutil 

with open('myfile', 'w') as outfile: 
    for infile in ('file1', 'file2', 'file3'): 
     shutil.copyfileobj(open(infile), outfile) 
+1

To działa, ale pozwól, że zapytam cię: Jaki jest sens biblioteki podprocesów, jeśli os.system już wykonuje zadanie? Mam wrażenie, że powinienem używać podprocesu, ponieważ jest to biblioteka poświęcona temu zadaniu, chociaż skoro robię to tylko dla siebie, tym razem będę dobrze używać os.system. – catatemypythoncode

+0

Biblioteka podprocesów jest znacznie bardziej elastyczna niż "os.system" i może dokładnie modelować 'os.system', ale jest również bardziej skomplikowana w użyciu. –

+11

'os.system' wystąpił przed' podprocesorem'. Ten pierwszy jest starszym interfejsem API, który zamierza zastąpić. – Santa

4

@ PoltoS Chcę dołączyć do niektórych plików, a następnie przetworzyć wynikowy plik. Myślałem, że używanie kota jest najłatwiejszą alternatywą. Czy istnieje lepszy/pythonic sposób to zrobić?

przedmiotu:

with open('myfile', 'w') as outfile: 
    for infilename in ['file1', 'file2', 'file3']: 
     with open(infilename) as infile: 
      outfile.write(infile.read()) 
165

Aby odpowiedzieć na oryginalne pytanie, aby przekierować wyjście, po prostu przekazać otwarty uchwyt pliku dla stdout argument subprocess.call:

# Use a list of args instead of a string 
input_files = ['file1', 'file2', 'file3'] 
my_cmd = ['cat'] + input_files 
with open('myfile', "w") as outfile: 
    subprocess.call(my_cmd, stdout=outfile) 

Ale jak inni zauważyłem, że użycie zewnętrznego polecenia, takiego jak cat, w tym celu jest całkowicie obce.

+2

To powinno być odpowiedzią na ogólne pytanie dotyczące orurowania podczas korzystania z powłoki z Python –

+25

To jest poprawna odpowiedź, a nie ta oznaczona jako poprawna. –

+0

To jest poprawna odpowiedź, najlepsze podejście. –

0

Jednym z interesujących przypadków byłoby zaktualizowanie pliku poprzez dołączenie do niego podobnego pliku. Wtedy nie trzeba tworzyć nowego pliku w procesie. Jest to szczególnie przydatne w przypadku, gdy należy dołączyć duży plik. Oto jedna z możliwości użycia linii poleceń teminal bezpośrednio z Pythona.

import subprocess32 as sub 

with open("A.csv","a") as f: 
    f.flush() 
    sub.Popen(["cat","temp.csv"],stdout=f) 
0
size = 'ffprobe -v error -show_entries format=size -of default=noprint_wrappers=1:nokey=1 dump.mp4 > file' 
proc = subprocess.Popen(shlex.split(size), shell=True) 
time.sleep(1) 
proc.terminate() #proc.kill() modify it by a suggestion 
size = "" 
with open('file', 'r') as infile: 
    for line in infile.readlines(): 
     size += line.strip() 

print(size) 
os.remove('file') 

Podczas korzystania podproces, proces musi być killed.This jest example.If nie zabić proces, plik będzie pusta i można przeczytać nothing.It można uruchomić na Windows. Nie mogę się upewnić, że może działać na Uniksie.

+0

To jest zły przykład kodu (nie będzie działać na Uniksie, demonstruje złe praktyki 'dla linii w .readlines():', 's + =') i 'proc.kill()' może prowadzić do utraty informacji ogólnie (nie pozwala na zakończenie subprocessu (na Unixie) - utracona zawartość jest tracona). W każdym razie notatka dotycząca buforowania jest bardziej odpowiednia jako komentarz. – jfs

+0

Uruchamiam go w systemie Windows jest OK (Ponieważ kill jest równoznaczne z zakończeniem w systemie Windows). Na Unixie powinieneś użyć proc.terminate(). @ J.F. Sebastian Nie mam systemu Unix na moim komputerze. – wyx

+0

Jeśli jesteś w systemie Windows, porzuć 'shlex.split()', upuść 'shell = True', upuść'> plik', upuść 'open()', itp. I użyj 'stdout = PIPE',' Timer (1, proc.terminate) .start() '; 'output = proc.communicate() [0]' zamiast tego. Oto [pełny przykład] (http://stackoverflow.com/a/27995163/4279). Więcej rozwiązań: [Zatrzymaj czytanie wyniku procesu w Pythonie bez zawieszania się?] (Http://stackoverflow.com/q/4417962/4279) Uwaga: nie ma wymogu w pytaniu, że musisz ręcznie zakończyć proces potomny - ty może zajmować się innymi kwestiami, np. proces może zachowywać się inaczej, jeśli jego standardowe wyjście jest tty, ale jest poza tematem. – jfs

Powiązane problemy