Python에서 하위 프로세스로 출력을 리디렉션하는 방법은 무엇입니까?


97

명령 줄에서 수행하는 작업 :

cat file1 file2 file3 > myfile

파이썬으로하고 싶은 것 :

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

하위 프로세스에서 이러한 명령을 실행하면 출력이 제공되지 않습니다. > myfilecat file1 file2 file3의 출력 을 Python으로 리디렉션 하지 않고 실행하고 싶 습니까?
PoltoS

@PoltoS 일부 파일을 결합한 다음 결과 파일을 처리하고 싶습니다. 고양이를 사용하는 것이 가장 쉬운 대안이라고 생각했습니다. 더 나은 / pythonic 방법이 있습니까?
catatemypythoncode

os.sendfile()기반 솔루션이 가능합니다. python에서 unix cat 명령 재현
jfs

1
출력 리디렉션 ( '>'또는 '>>')이 subprocess.Popen (적어도 Python 2.7에서는) (shell = True 모드에서)에서 작동하지 않는다고 생각합니다.이 예제에서는 다른 사람들이 지적했듯이 해결할 수 있습니다. 이것은 리디렉션을 사용하지 않는 것이지만 다른 경우에는 리디렉션이 유용합니다. 리디렉션 또는 파이핑이 하위 프로세스에서 지원되지 않는 경우 Popen이 문서화되어야합니다 (그리고 / 또는 os.system ()은 이것이 수정 될 때까지 사용되지 않아야 함)
Ribo

답변:


20

업데이트 : os.system은 권장되지 않지만 Python 3에서는 여전히 사용할 수 있습니다.


사용 os.system:

os.system(my_cmd)

정말로 하위 프로세스를 사용하려는 경우 솔루션은 다음과 같습니다 (대부분 하위 프로세스에 대한 문서에서 가져옴).

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

OTOH, 시스템 호출을 완전히 피할 수 있습니다.

import shutil

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

1
작동하지만 다음 질문을하겠습니다 : os.system이 이미 작업을 완료 한 경우 하위 프로세스 라이브러리의 요점은 무엇입니까? 이 작업에 전념하는 라이브러리이기 때문에 대신 하위 프로세스를 사용해야한다는 느낌이 들지만 이번에는 os.system을 사용해도 괜찮을 것입니다.
catatemypythoncode

하위 프로세스 라이브러리는보다 훨씬 유연 os.system하고 os.system정확하게 모델링 할 수 있지만 작업하기가 더 복잡합니다.
Marcelo Cantos

13
os.system전에 왔습니다 subprocess. 전자는 후자가 대체하려는 레거시 API입니다.
Santa

5
@catatemypythoncode : os.system()또는 shell=True. 하위 프로세스의 출력을 리디렉션하려면 Ryan Thompson의 답변에stdout 표시된대로 매개 변수를 사용하십시오 . 귀하의 경우 에는 하위 프로세스 ( ) 가 필요하지 않지만 순수 Python을 사용하여 파일을 연결할 수 있습니다. cat
jfs

4
OTOH = 반면에
Cephlin

272

에서 파이썬 3.5 출력을 리디렉션, 단지에 대한 열린 파일 핸들을 전달 stdout하는 인수 subprocess.run:

# 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.run(my_cmd, stdout=outfile)

다른 사람들이 지적했듯이 cat이러한 목적으로 외부 명령을 사용하는 것은 완전히 관련이 없습니다.


9
파이썬에서 쉘 사용할 때 배관의 일반적인 질문에 대한 대답해야한다
Kaushik이 Ghose

47
이것은 정답이 아니라 정답입니다.
Justin Blake

7
subprocess.run(my_cmd, stdout=outfile)대체되는 Python 3.5 이상 사용의 경우subprocess.call(...)
Austin Yates

1
그들이 fileno 필드가없는 경우 참고로, 이것은 사용자 정의 파일 오브젝트 작동하지 않습니다 (그들이 실제 파일이 아닌 경우.)
엘리 MIRON

1
Python <3.5는 현재 더 이상 사용되지 않으므로 @AustinYates라는 의견으로 답변을 업데이트했습니다.
Greg Dubicki

5

@PoltoS 일부 파일을 결합한 다음 결과 파일을 처리하고 싶습니다. 고양이를 사용하는 것이 가장 쉬운 대안이라고 생각했습니다. 더 나은 / pythonic 방법이 있습니까?

물론이야:

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

1
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')

subprocess 를 사용 하면 프로세스가 종료되어야합니다. 이는 예입니다. process를 종료하지 않으면 파일 이 비어 있고 아무것도 읽을 수 없습니다 . Windows에서 실행할 수 있습니다. 유닉스에서 실행됩니다.


1
그것은 (이것은 유닉스에서 작동하지 않습니다, 그것은 나쁜 관행을 보여줍니다 나쁜 코드의 예입니다 for line in .readlines():, s +=)과 proc.kill()) 일반적으로 정보가 손실 될 수 있습니다 (이 서브 프로세스는 유닉스 (정상적으로 종료 할 수 없습니다 - h 제되지 않은 내용이 손실됩니다 ). 어쨌든 버퍼링에 대한 메모는 주석으로 더 적절합니다.
jfs

Windows에서 실행해도 괜찮습니다 (kill은 Windows에서 종료하는 것과 같기 때문입니다). Unix에서는 proc.terminate ()를 사용해야합니다. @ JF Sebastian 컴퓨터에 Unix 시스템이 없습니다.
wyx

Windows를 사용하는 경우 drop shlex.split(), drop shell=True, drop >file, drop open()등을 사용하고 stdout=PIPE, Timer(1, proc.terminate).start(); output = proc.communicate()[0]대신. 여기에 완전한 예가 있습니다. 추가 솔루션 : 중단없이 Python에서 프로세스 출력 읽기를 중지 하시겠습니까? 참고 : 자식 프로세스를 수동으로 종료해야한다는 질문에 대한 요구 사항은 없습니다. 다른 문제를 해결할 수 있습니다. 예를 들어 표준 출력이 tty이지만 주제를 벗어난 경우 프로세스가 다르게 동작 할 수 있습니다.
jfs

0

한 가지 흥미로운 경우는 유사한 파일을 추가하여 파일을 업데이트하는 것입니다. 그러면 프로세스에서 새 파일을 만들 필요가 없습니다. 큰 파일을 추가해야하는 경우 특히 유용합니다. 다음은 파이썬에서 직접 teminal 명령 줄을 사용하는 한 가지 가능성입니다.

import subprocess32 as sub

with open("A.csv","a") as f:
    f.flush()
    sub.Popen(["cat","temp.csv"],stdout=f)
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.